mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 12:32:08 -06:00
Improve isDeeplyNestedType for homomorphic mapped types (#56169)
This commit is contained in:
parent
8af8f3c4d1
commit
b76b4c26ca
@ -23568,22 +23568,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
!hasBaseType(checkClass, getDeclaringClass(p)) : false) ? undefined : checkClass;
|
||||
}
|
||||
|
||||
// Return true if the given type is deeply nested. We consider this to be the case when structural type comparisons
|
||||
// for maxDepth or more occurrences or instantiations of the same type have been recorded on the given stack. The
|
||||
// "sameness" of instantiations is determined by the getRecursionIdentity function. An intersection is considered
|
||||
// deeply nested if any constituent of the intersection is deeply nested. It is possible, though highly unlikely, for
|
||||
// the deeply nested check to be true in a situation where a chain of instantiations is not infinitely expanding.
|
||||
// Effectively, we will generate a false positive when two types are structurally equal to at least maxDepth levels,
|
||||
// but unequal at some level beyond that.
|
||||
// In addition, this will also detect when an indexed access has been chained off of maxDepth more times (which is
|
||||
// essentially the dual of the structural comparison), and likewise mark the type as deeply nested, potentially adding
|
||||
// false positives for finite but deeply expanding indexed accesses (eg, for `Q[P1][P2][P3][P4][P5]`).
|
||||
// It also detects when a recursive type reference has expanded maxDepth or more times, e.g. if the true branch of
|
||||
// `type A<T> = null extends T ? [A<NonNullable<T>>] : [T]`
|
||||
// has expanded into `[A<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T>>>>>>]`. In such cases we need
|
||||
// to terminate the expansion, and we do so here.
|
||||
// Return true if the given type is deeply nested. We consider this to be the case when the given stack contains
|
||||
// maxDepth or more occurrences of types with the same recursion identity as the given type. The recursion identity
|
||||
// provides a shared identity for type instantiations that repeat in some (possibly infinite) pattern. For example,
|
||||
// in `type Deep<T> = { next: Deep<Deep<T>> }`, repeatedly referencing the `next` property leads to an infinite
|
||||
// sequence of ever deeper instantiations with the same recursion identity (in this case the symbol associated with
|
||||
// the object type literal).
|
||||
// A homomorphic mapped type is considered deeply nested if its target type is deeply nested, and an intersection is
|
||||
// considered deeply nested if any constituent of the intersection is deeply nested.
|
||||
// It is possible, though highly unlikely, for the deeply nested check to be true in a situation where a chain of
|
||||
// instantiations is not infinitely expanding. Effectively, we will generate a false positive when two types are
|
||||
// structurally equal to at least maxDepth levels, but unequal at some level beyond that.
|
||||
function isDeeplyNestedType(type: Type, stack: Type[], depth: number, maxDepth = 3): boolean {
|
||||
if (depth >= maxDepth) {
|
||||
if ((getObjectFlags(type) & ObjectFlags.InstantiatedMapped) === ObjectFlags.InstantiatedMapped) {
|
||||
type = getMappedTargetWithSymbol(type);
|
||||
}
|
||||
if (type.flags & TypeFlags.Intersection) {
|
||||
return some((type as IntersectionType).types, t => isDeeplyNestedType(t, stack, depth, maxDepth));
|
||||
}
|
||||
@ -23592,7 +23592,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
let lastTypeId = 0;
|
||||
for (let i = 0; i < depth; i++) {
|
||||
const t = stack[i];
|
||||
if (t.flags & TypeFlags.Intersection ? some((t as IntersectionType).types, u => getRecursionIdentity(u) === identity) : getRecursionIdentity(t) === identity) {
|
||||
if (hasMatchingRecursionIdentity(t, identity)) {
|
||||
// We only count occurrences with a higher type id than the previous occurrence, since higher
|
||||
// type ids are an indicator of newer instantiations caused by recursion.
|
||||
if (t.id >= lastTypeId) {
|
||||
@ -23608,6 +23608,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unwrap nested homomorphic mapped types and return the deepest target type that has a symbol. This better
|
||||
// preserves unique type identities for mapped types applied to explicitly written object literals. For example
|
||||
// in `Mapped<{ x: Mapped<{ x: Mapped<{ x: string }>}>}>`, each of the mapped type applications will have a
|
||||
// unique recursion identity (that of their target object type literal) and thus avoid appearing deeply nested.
|
||||
function getMappedTargetWithSymbol(type: Type) {
|
||||
let target;
|
||||
while (
|
||||
(getObjectFlags(type) & ObjectFlags.InstantiatedMapped) === ObjectFlags.InstantiatedMapped &&
|
||||
(target = getModifiersTypeFromMappedType(type as MappedType)) &&
|
||||
(target.symbol || target.flags & TypeFlags.Intersection && some((target as IntersectionType).types, t => !!t.symbol))
|
||||
) {
|
||||
type = target;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function hasMatchingRecursionIdentity(type: Type, identity: object): boolean {
|
||||
if ((getObjectFlags(type) & ObjectFlags.InstantiatedMapped) === ObjectFlags.InstantiatedMapped) {
|
||||
type = getMappedTargetWithSymbol(type);
|
||||
}
|
||||
if (type.flags & TypeFlags.Intersection) {
|
||||
return some((type as IntersectionType).types, t => hasMatchingRecursionIdentity(t, identity));
|
||||
}
|
||||
return getRecursionIdentity(type) === identity;
|
||||
}
|
||||
|
||||
// The recursion identity of a type is an object identity that is shared among multiple instantiations of the type.
|
||||
// We track recursion identities in order to identify deeply nested and possibly infinite type instantiations with
|
||||
// the same origin. For example, when type parameters are in scope in an object type such as { x: T }, all
|
||||
@ -23623,28 +23649,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// unique AST node.
|
||||
return (type as TypeReference).node!;
|
||||
}
|
||||
if (type.symbol) {
|
||||
// We track object types that have a symbol by that symbol (representing the origin of the type).
|
||||
if (getObjectFlags(type) & ObjectFlags.Mapped) {
|
||||
// When a homomorphic mapped type is applied to a type with a symbol, we use the symbol of that
|
||||
// type as the recursion identity. This is a better strategy than using the symbol of the mapped
|
||||
// type, which doesn't work well for recursive mapped types.
|
||||
type = getMappedTargetWithSymbol(type);
|
||||
}
|
||||
if (!(getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol.flags & SymbolFlags.Class)) {
|
||||
// We exclude the static side of a class since it shares its symbol with the instance side.
|
||||
return type.symbol;
|
||||
}
|
||||
if (type.symbol && !(getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol.flags & SymbolFlags.Class)) {
|
||||
// We track object types that have a symbol by that symbol (representing the origin of the type), but
|
||||
// exclude the static side of a class since it shares its symbol with the instance side.
|
||||
return type.symbol;
|
||||
}
|
||||
if (isTupleType(type)) {
|
||||
return type.target;
|
||||
}
|
||||
}
|
||||
if (type.flags & TypeFlags.TypeParameter) {
|
||||
// We use the symbol of the type parameter such that all "fresh" instantiations of that type parameter
|
||||
// have the same recursion identity.
|
||||
return type.symbol;
|
||||
}
|
||||
if (type.flags & TypeFlags.IndexedAccess) {
|
||||
// Identity is the leftmost object type in a chain of indexed accesses, eg, in A[P][Q] it is A
|
||||
// Identity is the leftmost object type in a chain of indexed accesses, eg, in A[P1][P2][P3] it is A.
|
||||
do {
|
||||
type = (type as IndexedAccessType).objectType;
|
||||
}
|
||||
@ -23658,14 +23678,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return type;
|
||||
}
|
||||
|
||||
function getMappedTargetWithSymbol(type: Type) {
|
||||
let target = type;
|
||||
while ((getObjectFlags(target) & ObjectFlags.InstantiatedMapped) === ObjectFlags.InstantiatedMapped && isMappedTypeWithKeyofConstraintDeclaration(target as MappedType)) {
|
||||
target = getModifiersTypeFromMappedType(target as MappedType);
|
||||
}
|
||||
return target.symbol ? target : type;
|
||||
}
|
||||
|
||||
function isPropertyIdenticalTo(sourceProp: Symbol, targetProp: Symbol): boolean {
|
||||
return compareProperties(sourceProp, targetProp, compareTypesIdentical) !== Ternary.False;
|
||||
}
|
||||
|
||||
@ -4,9 +4,19 @@ deeplyNestedMappedTypes.ts(9,7): error TS2322: Type 'Id<{ x: { y: { z: { a: { b:
|
||||
deeplyNestedMappedTypes.ts(17,7): error TS2322: Type 'Id2<{ x: { y: { z: { a: { b: { c: number; }; }; }; }; }; }>' is not assignable to type 'Id2<{ x: { y: { z: { a: { b: { c: string; }; }; }; }; }; }>'.
|
||||
The types of 'x.y.z.a.b.c' are incompatible between these types.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
deeplyNestedMappedTypes.ts(69,5): error TS2322: Type '{ level1: { level2: { foo: string; }; }; }[]' is not assignable to type '{ level1: { level2: { foo: string; bar: string; }; }; }[]'.
|
||||
Type '{ level1: { level2: { foo: string; }; }; }' is not assignable to type '{ level1: { level2: { foo: string; bar: string; }; }; }'.
|
||||
The types of 'level1.level2' are incompatible between these types.
|
||||
Property 'bar' is missing in type '{ foo: string; }' but required in type '{ foo: string; bar: string; }'.
|
||||
deeplyNestedMappedTypes.ts(73,5): error TS2322: Type '{ level1: { level2: { foo: string; }; }; }[]' is not assignable to type 'T'.
|
||||
'T' could be instantiated with an arbitrary type which could be unrelated to '{ level1: { level2: { foo: string; }; }; }[]'.
|
||||
deeplyNestedMappedTypes.ts(77,5): error TS2322: Type '{ level1: { level2: { foo: string; }; }; }[]' is not assignable to type '{ level1: { level2: { foo: string; bar: string; }; }; }[]'.
|
||||
Type '{ level1: { level2: { foo: string; }; }; }' is not assignable to type '{ level1: { level2: { foo: string; bar: string; }; }; }'.
|
||||
The types of 'level1.level2' are incompatible between these types.
|
||||
Property 'bar' is missing in type '{ foo: string; }' but required in type '{ foo: string; bar: string; }'.
|
||||
|
||||
|
||||
==== deeplyNestedMappedTypes.ts (2 errors) ====
|
||||
==== deeplyNestedMappedTypes.ts (5 errors) ====
|
||||
// Simplified repro from #55535
|
||||
|
||||
type Id<T> = { [K in keyof T]: Id<T[K]> };
|
||||
@ -60,4 +70,109 @@ deeplyNestedMappedTypes.ts(17,7): error TS2322: Type 'Id2<{ x: { y: { z: { a: {
|
||||
|
||||
declare const bar1: Bar1;
|
||||
const bar2: Bar2 = bar1; // Error expected
|
||||
|
||||
// Repro from #56138
|
||||
|
||||
export type Input = Static<typeof Input>
|
||||
export const Input = Type.Object({
|
||||
level1: Type.Object({
|
||||
level2: Type.Object({
|
||||
foo: Type.String(),
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
export type Output = Static<typeof Output>
|
||||
export const Output = Type.Object({
|
||||
level1: Type.Object({
|
||||
level2: Type.Object({
|
||||
foo: Type.String(),
|
||||
bar: Type.String(),
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function problematicFunction1(ors: Input[]): Output[] {
|
||||
return ors; // Error
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '{ level1: { level2: { foo: string; }; }; }[]' is not assignable to type '{ level1: { level2: { foo: string; bar: string; }; }; }[]'.
|
||||
!!! error TS2322: Type '{ level1: { level2: { foo: string; }; }; }' is not assignable to type '{ level1: { level2: { foo: string; bar: string; }; }; }'.
|
||||
!!! error TS2322: The types of 'level1.level2' are incompatible between these types.
|
||||
!!! error TS2322: Property 'bar' is missing in type '{ foo: string; }' but required in type '{ foo: string; bar: string; }'.
|
||||
!!! related TS2728 deeplyNestedMappedTypes.ts:63:13: 'bar' is declared here.
|
||||
}
|
||||
|
||||
function problematicFunction2<T extends Output[]>(ors: Input[]): T {
|
||||
return ors; // Error
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '{ level1: { level2: { foo: string; }; }; }[]' is not assignable to type 'T'.
|
||||
!!! error TS2322: 'T' could be instantiated with an arbitrary type which could be unrelated to '{ level1: { level2: { foo: string; }; }; }[]'.
|
||||
}
|
||||
|
||||
function problematicFunction3(ors: (typeof Input.static)[]): Output[] {
|
||||
return ors; // Error
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '{ level1: { level2: { foo: string; }; }; }[]' is not assignable to type '{ level1: { level2: { foo: string; bar: string; }; }; }[]'.
|
||||
!!! error TS2322: Type '{ level1: { level2: { foo: string; }; }; }' is not assignable to type '{ level1: { level2: { foo: string; bar: string; }; }; }'.
|
||||
!!! error TS2322: The types of 'level1.level2' are incompatible between these types.
|
||||
!!! error TS2322: Property 'bar' is missing in type '{ foo: string; }' but required in type '{ foo: string; bar: string; }'.
|
||||
!!! related TS2728 deeplyNestedMappedTypes.ts:63:13: 'bar' is declared here.
|
||||
}
|
||||
|
||||
export type Evaluate<T> = T extends infer O ? { [K in keyof O]: O[K] } : never
|
||||
|
||||
export declare const Readonly: unique symbol;
|
||||
export declare const Optional: unique symbol;
|
||||
export declare const Hint: unique symbol;
|
||||
export declare const Kind: unique symbol;
|
||||
|
||||
export interface TKind {
|
||||
[Kind]: string
|
||||
}
|
||||
export interface TSchema extends TKind {
|
||||
[Readonly]?: string
|
||||
[Optional]?: string
|
||||
[Hint]?: string
|
||||
params: unknown[]
|
||||
static: unknown
|
||||
}
|
||||
|
||||
export type TReadonlyOptional<T extends TSchema> = TOptional<T> & TReadonly<T>
|
||||
export type TReadonly<T extends TSchema> = T & { [Readonly]: 'Readonly' }
|
||||
export type TOptional<T extends TSchema> = T & { [Optional]: 'Optional' }
|
||||
|
||||
export interface TString extends TSchema {
|
||||
[Kind]: 'String';
|
||||
static: string;
|
||||
type: 'string';
|
||||
}
|
||||
|
||||
export type ReadonlyOptionalPropertyKeys<T extends TProperties> = { [K in keyof T]: T[K] extends TReadonly<TSchema> ? (T[K] extends TOptional<T[K]> ? K : never) : never }[keyof T]
|
||||
export type ReadonlyPropertyKeys<T extends TProperties> = { [K in keyof T]: T[K] extends TReadonly<TSchema> ? (T[K] extends TOptional<T[K]> ? never : K) : never }[keyof T]
|
||||
export type OptionalPropertyKeys<T extends TProperties> = { [K in keyof T]: T[K] extends TOptional<TSchema> ? (T[K] extends TReadonly<T[K]> ? never : K) : never }[keyof T]
|
||||
export type RequiredPropertyKeys<T extends TProperties> = keyof Omit<T, ReadonlyOptionalPropertyKeys<T> | ReadonlyPropertyKeys<T> | OptionalPropertyKeys<T>>
|
||||
export type PropertiesReducer<T extends TProperties, R extends Record<keyof any, unknown>> = Evaluate<(
|
||||
Readonly<Partial<Pick<R, ReadonlyOptionalPropertyKeys<T>>>> &
|
||||
Readonly<Pick<R, ReadonlyPropertyKeys<T>>> &
|
||||
Partial<Pick<R, OptionalPropertyKeys<T>>> &
|
||||
Required<Pick<R, RequiredPropertyKeys<T>>>
|
||||
)>
|
||||
export type PropertiesReduce<T extends TProperties, P extends unknown[]> = PropertiesReducer<T, {
|
||||
[K in keyof T]: Static<T[K], P>
|
||||
}>
|
||||
export type TPropertyKey = string | number
|
||||
export type TProperties = Record<TPropertyKey, TSchema>
|
||||
export interface TObject<T extends TProperties = TProperties> extends TSchema {
|
||||
[Kind]: 'Object'
|
||||
static: PropertiesReduce<T, this['params']>
|
||||
type: 'object'
|
||||
properties: T
|
||||
}
|
||||
|
||||
export type Static<T extends TSchema, P extends unknown[] = []> = (T & { params: P; })['static']
|
||||
|
||||
declare namespace Type {
|
||||
function Object<T extends TProperties>(object: T): TObject<T>
|
||||
function String(): TString
|
||||
}
|
||||
|
||||
@ -175,3 +175,384 @@ const bar2: Bar2 = bar1; // Error expected
|
||||
>Bar2 : Symbol(Bar2, Decl(deeplyNestedMappedTypes.ts, 40, 48))
|
||||
>bar1 : Symbol(bar1, Decl(deeplyNestedMappedTypes.ts, 43, 13))
|
||||
|
||||
// Repro from #56138
|
||||
|
||||
export type Input = Static<typeof Input>
|
||||
>Input : Symbol(Input, Decl(deeplyNestedMappedTypes.ts, 44, 24), Decl(deeplyNestedMappedTypes.ts, 49, 12))
|
||||
>Static : Symbol(Static, Decl(deeplyNestedMappedTypes.ts, 127, 1))
|
||||
>Input : Symbol(Input, Decl(deeplyNestedMappedTypes.ts, 44, 24), Decl(deeplyNestedMappedTypes.ts, 49, 12))
|
||||
|
||||
export const Input = Type.Object({
|
||||
>Input : Symbol(Input, Decl(deeplyNestedMappedTypes.ts, 44, 24), Decl(deeplyNestedMappedTypes.ts, 49, 12))
|
||||
>Type.Object : Symbol(Type.Object, Decl(deeplyNestedMappedTypes.ts, 131, 24))
|
||||
>Type : Symbol(Type, Decl(deeplyNestedMappedTypes.ts, 129, 96))
|
||||
>Object : Symbol(Type.Object, Decl(deeplyNestedMappedTypes.ts, 131, 24))
|
||||
|
||||
level1: Type.Object({
|
||||
>level1 : Symbol(level1, Decl(deeplyNestedMappedTypes.ts, 49, 34))
|
||||
>Type.Object : Symbol(Type.Object, Decl(deeplyNestedMappedTypes.ts, 131, 24))
|
||||
>Type : Symbol(Type, Decl(deeplyNestedMappedTypes.ts, 129, 96))
|
||||
>Object : Symbol(Type.Object, Decl(deeplyNestedMappedTypes.ts, 131, 24))
|
||||
|
||||
level2: Type.Object({
|
||||
>level2 : Symbol(level2, Decl(deeplyNestedMappedTypes.ts, 50, 25))
|
||||
>Type.Object : Symbol(Type.Object, Decl(deeplyNestedMappedTypes.ts, 131, 24))
|
||||
>Type : Symbol(Type, Decl(deeplyNestedMappedTypes.ts, 129, 96))
|
||||
>Object : Symbol(Type.Object, Decl(deeplyNestedMappedTypes.ts, 131, 24))
|
||||
|
||||
foo: Type.String(),
|
||||
>foo : Symbol(foo, Decl(deeplyNestedMappedTypes.ts, 51, 29))
|
||||
>Type.String : Symbol(Type.String, Decl(deeplyNestedMappedTypes.ts, 132, 65))
|
||||
>Type : Symbol(Type, Decl(deeplyNestedMappedTypes.ts, 129, 96))
|
||||
>String : Symbol(Type.String, Decl(deeplyNestedMappedTypes.ts, 132, 65))
|
||||
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
export type Output = Static<typeof Output>
|
||||
>Output : Symbol(Output, Decl(deeplyNestedMappedTypes.ts, 55, 2), Decl(deeplyNestedMappedTypes.ts, 58, 12))
|
||||
>Static : Symbol(Static, Decl(deeplyNestedMappedTypes.ts, 127, 1))
|
||||
>Output : Symbol(Output, Decl(deeplyNestedMappedTypes.ts, 55, 2), Decl(deeplyNestedMappedTypes.ts, 58, 12))
|
||||
|
||||
export const Output = Type.Object({
|
||||
>Output : Symbol(Output, Decl(deeplyNestedMappedTypes.ts, 55, 2), Decl(deeplyNestedMappedTypes.ts, 58, 12))
|
||||
>Type.Object : Symbol(Type.Object, Decl(deeplyNestedMappedTypes.ts, 131, 24))
|
||||
>Type : Symbol(Type, Decl(deeplyNestedMappedTypes.ts, 129, 96))
|
||||
>Object : Symbol(Type.Object, Decl(deeplyNestedMappedTypes.ts, 131, 24))
|
||||
|
||||
level1: Type.Object({
|
||||
>level1 : Symbol(level1, Decl(deeplyNestedMappedTypes.ts, 58, 35))
|
||||
>Type.Object : Symbol(Type.Object, Decl(deeplyNestedMappedTypes.ts, 131, 24))
|
||||
>Type : Symbol(Type, Decl(deeplyNestedMappedTypes.ts, 129, 96))
|
||||
>Object : Symbol(Type.Object, Decl(deeplyNestedMappedTypes.ts, 131, 24))
|
||||
|
||||
level2: Type.Object({
|
||||
>level2 : Symbol(level2, Decl(deeplyNestedMappedTypes.ts, 59, 25))
|
||||
>Type.Object : Symbol(Type.Object, Decl(deeplyNestedMappedTypes.ts, 131, 24))
|
||||
>Type : Symbol(Type, Decl(deeplyNestedMappedTypes.ts, 129, 96))
|
||||
>Object : Symbol(Type.Object, Decl(deeplyNestedMappedTypes.ts, 131, 24))
|
||||
|
||||
foo: Type.String(),
|
||||
>foo : Symbol(foo, Decl(deeplyNestedMappedTypes.ts, 60, 29))
|
||||
>Type.String : Symbol(Type.String, Decl(deeplyNestedMappedTypes.ts, 132, 65))
|
||||
>Type : Symbol(Type, Decl(deeplyNestedMappedTypes.ts, 129, 96))
|
||||
>String : Symbol(Type.String, Decl(deeplyNestedMappedTypes.ts, 132, 65))
|
||||
|
||||
bar: Type.String(),
|
||||
>bar : Symbol(bar, Decl(deeplyNestedMappedTypes.ts, 61, 31))
|
||||
>Type.String : Symbol(Type.String, Decl(deeplyNestedMappedTypes.ts, 132, 65))
|
||||
>Type : Symbol(Type, Decl(deeplyNestedMappedTypes.ts, 129, 96))
|
||||
>String : Symbol(Type.String, Decl(deeplyNestedMappedTypes.ts, 132, 65))
|
||||
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function problematicFunction1(ors: Input[]): Output[] {
|
||||
>problematicFunction1 : Symbol(problematicFunction1, Decl(deeplyNestedMappedTypes.ts, 65, 2))
|
||||
>ors : Symbol(ors, Decl(deeplyNestedMappedTypes.ts, 67, 30))
|
||||
>Input : Symbol(Input, Decl(deeplyNestedMappedTypes.ts, 44, 24), Decl(deeplyNestedMappedTypes.ts, 49, 12))
|
||||
>Output : Symbol(Output, Decl(deeplyNestedMappedTypes.ts, 55, 2), Decl(deeplyNestedMappedTypes.ts, 58, 12))
|
||||
|
||||
return ors; // Error
|
||||
>ors : Symbol(ors, Decl(deeplyNestedMappedTypes.ts, 67, 30))
|
||||
}
|
||||
|
||||
function problematicFunction2<T extends Output[]>(ors: Input[]): T {
|
||||
>problematicFunction2 : Symbol(problematicFunction2, Decl(deeplyNestedMappedTypes.ts, 69, 1))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 71, 30))
|
||||
>Output : Symbol(Output, Decl(deeplyNestedMappedTypes.ts, 55, 2), Decl(deeplyNestedMappedTypes.ts, 58, 12))
|
||||
>ors : Symbol(ors, Decl(deeplyNestedMappedTypes.ts, 71, 50))
|
||||
>Input : Symbol(Input, Decl(deeplyNestedMappedTypes.ts, 44, 24), Decl(deeplyNestedMappedTypes.ts, 49, 12))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 71, 30))
|
||||
|
||||
return ors; // Error
|
||||
>ors : Symbol(ors, Decl(deeplyNestedMappedTypes.ts, 71, 50))
|
||||
}
|
||||
|
||||
function problematicFunction3(ors: (typeof Input.static)[]): Output[] {
|
||||
>problematicFunction3 : Symbol(problematicFunction3, Decl(deeplyNestedMappedTypes.ts, 73, 1))
|
||||
>ors : Symbol(ors, Decl(deeplyNestedMappedTypes.ts, 75, 30))
|
||||
>Input.static : Symbol(TObject.static, Decl(deeplyNestedMappedTypes.ts, 123, 20))
|
||||
>Input : Symbol(Input, Decl(deeplyNestedMappedTypes.ts, 44, 24), Decl(deeplyNestedMappedTypes.ts, 49, 12))
|
||||
>static : Symbol(TObject.static, Decl(deeplyNestedMappedTypes.ts, 123, 20))
|
||||
>Output : Symbol(Output, Decl(deeplyNestedMappedTypes.ts, 55, 2), Decl(deeplyNestedMappedTypes.ts, 58, 12))
|
||||
|
||||
return ors; // Error
|
||||
>ors : Symbol(ors, Decl(deeplyNestedMappedTypes.ts, 75, 30))
|
||||
}
|
||||
|
||||
export type Evaluate<T> = T extends infer O ? { [K in keyof O]: O[K] } : never
|
||||
>Evaluate : Symbol(Evaluate, Decl(deeplyNestedMappedTypes.ts, 77, 1))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 79, 21))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 79, 21))
|
||||
>O : Symbol(O, Decl(deeplyNestedMappedTypes.ts, 79, 41))
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 79, 49))
|
||||
>O : Symbol(O, Decl(deeplyNestedMappedTypes.ts, 79, 41))
|
||||
>O : Symbol(O, Decl(deeplyNestedMappedTypes.ts, 79, 41))
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 79, 49))
|
||||
|
||||
export declare const Readonly: unique symbol;
|
||||
>Readonly : Symbol(Readonly, Decl(deeplyNestedMappedTypes.ts, 81, 20))
|
||||
|
||||
export declare const Optional: unique symbol;
|
||||
>Optional : Symbol(Optional, Decl(deeplyNestedMappedTypes.ts, 82, 20))
|
||||
|
||||
export declare const Hint: unique symbol;
|
||||
>Hint : Symbol(Hint, Decl(deeplyNestedMappedTypes.ts, 83, 20))
|
||||
|
||||
export declare const Kind: unique symbol;
|
||||
>Kind : Symbol(Kind, Decl(deeplyNestedMappedTypes.ts, 84, 20))
|
||||
|
||||
export interface TKind {
|
||||
>TKind : Symbol(TKind, Decl(deeplyNestedMappedTypes.ts, 84, 41))
|
||||
|
||||
[Kind]: string
|
||||
>[Kind] : Symbol(TKind[Kind], Decl(deeplyNestedMappedTypes.ts, 86, 24))
|
||||
>Kind : Symbol(Kind, Decl(deeplyNestedMappedTypes.ts, 84, 20))
|
||||
}
|
||||
export interface TSchema extends TKind {
|
||||
>TSchema : Symbol(TSchema, Decl(deeplyNestedMappedTypes.ts, 88, 1))
|
||||
>TKind : Symbol(TKind, Decl(deeplyNestedMappedTypes.ts, 84, 41))
|
||||
|
||||
[Readonly]?: string
|
||||
>[Readonly] : Symbol(TSchema[Readonly], Decl(deeplyNestedMappedTypes.ts, 89, 40))
|
||||
>Readonly : Symbol(Readonly, Decl(deeplyNestedMappedTypes.ts, 81, 20))
|
||||
|
||||
[Optional]?: string
|
||||
>[Optional] : Symbol(TSchema[Optional], Decl(deeplyNestedMappedTypes.ts, 90, 23))
|
||||
>Optional : Symbol(Optional, Decl(deeplyNestedMappedTypes.ts, 82, 20))
|
||||
|
||||
[Hint]?: string
|
||||
>[Hint] : Symbol(TSchema[Hint], Decl(deeplyNestedMappedTypes.ts, 91, 23))
|
||||
>Hint : Symbol(Hint, Decl(deeplyNestedMappedTypes.ts, 83, 20))
|
||||
|
||||
params: unknown[]
|
||||
>params : Symbol(TSchema.params, Decl(deeplyNestedMappedTypes.ts, 92, 19))
|
||||
|
||||
static: unknown
|
||||
>static : Symbol(TSchema.static, Decl(deeplyNestedMappedTypes.ts, 93, 21))
|
||||
}
|
||||
|
||||
export type TReadonlyOptional<T extends TSchema> = TOptional<T> & TReadonly<T>
|
||||
>TReadonlyOptional : Symbol(TReadonlyOptional, Decl(deeplyNestedMappedTypes.ts, 95, 1))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 97, 30))
|
||||
>TSchema : Symbol(TSchema, Decl(deeplyNestedMappedTypes.ts, 88, 1))
|
||||
>TOptional : Symbol(TOptional, Decl(deeplyNestedMappedTypes.ts, 98, 73))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 97, 30))
|
||||
>TReadonly : Symbol(TReadonly, Decl(deeplyNestedMappedTypes.ts, 97, 78))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 97, 30))
|
||||
|
||||
export type TReadonly<T extends TSchema> = T & { [Readonly]: 'Readonly' }
|
||||
>TReadonly : Symbol(TReadonly, Decl(deeplyNestedMappedTypes.ts, 97, 78))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 98, 22))
|
||||
>TSchema : Symbol(TSchema, Decl(deeplyNestedMappedTypes.ts, 88, 1))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 98, 22))
|
||||
>[Readonly] : Symbol([Readonly], Decl(deeplyNestedMappedTypes.ts, 98, 48))
|
||||
>Readonly : Symbol(Readonly, Decl(deeplyNestedMappedTypes.ts, 81, 20))
|
||||
|
||||
export type TOptional<T extends TSchema> = T & { [Optional]: 'Optional' }
|
||||
>TOptional : Symbol(TOptional, Decl(deeplyNestedMappedTypes.ts, 98, 73))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 99, 22))
|
||||
>TSchema : Symbol(TSchema, Decl(deeplyNestedMappedTypes.ts, 88, 1))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 99, 22))
|
||||
>[Optional] : Symbol([Optional], Decl(deeplyNestedMappedTypes.ts, 99, 48))
|
||||
>Optional : Symbol(Optional, Decl(deeplyNestedMappedTypes.ts, 82, 20))
|
||||
|
||||
export interface TString extends TSchema {
|
||||
>TString : Symbol(TString, Decl(deeplyNestedMappedTypes.ts, 99, 73))
|
||||
>TSchema : Symbol(TSchema, Decl(deeplyNestedMappedTypes.ts, 88, 1))
|
||||
|
||||
[Kind]: 'String';
|
||||
>[Kind] : Symbol(TString[Kind], Decl(deeplyNestedMappedTypes.ts, 101, 42))
|
||||
>Kind : Symbol(Kind, Decl(deeplyNestedMappedTypes.ts, 84, 20))
|
||||
|
||||
static: string;
|
||||
>static : Symbol(TString.static, Decl(deeplyNestedMappedTypes.ts, 102, 21))
|
||||
|
||||
type: 'string';
|
||||
>type : Symbol(TString.type, Decl(deeplyNestedMappedTypes.ts, 103, 19))
|
||||
}
|
||||
|
||||
export type ReadonlyOptionalPropertyKeys<T extends TProperties> = { [K in keyof T]: T[K] extends TReadonly<TSchema> ? (T[K] extends TOptional<T[K]> ? K : never) : never }[keyof T]
|
||||
>ReadonlyOptionalPropertyKeys : Symbol(ReadonlyOptionalPropertyKeys, Decl(deeplyNestedMappedTypes.ts, 105, 1))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 107, 41))
|
||||
>TProperties : Symbol(TProperties, Decl(deeplyNestedMappedTypes.ts, 120, 42))
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 107, 69))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 107, 41))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 107, 41))
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 107, 69))
|
||||
>TReadonly : Symbol(TReadonly, Decl(deeplyNestedMappedTypes.ts, 97, 78))
|
||||
>TSchema : Symbol(TSchema, Decl(deeplyNestedMappedTypes.ts, 88, 1))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 107, 41))
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 107, 69))
|
||||
>TOptional : Symbol(TOptional, Decl(deeplyNestedMappedTypes.ts, 98, 73))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 107, 41))
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 107, 69))
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 107, 69))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 107, 41))
|
||||
|
||||
export type ReadonlyPropertyKeys<T extends TProperties> = { [K in keyof T]: T[K] extends TReadonly<TSchema> ? (T[K] extends TOptional<T[K]> ? never : K) : never }[keyof T]
|
||||
>ReadonlyPropertyKeys : Symbol(ReadonlyPropertyKeys, Decl(deeplyNestedMappedTypes.ts, 107, 179))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 108, 33))
|
||||
>TProperties : Symbol(TProperties, Decl(deeplyNestedMappedTypes.ts, 120, 42))
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 108, 61))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 108, 33))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 108, 33))
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 108, 61))
|
||||
>TReadonly : Symbol(TReadonly, Decl(deeplyNestedMappedTypes.ts, 97, 78))
|
||||
>TSchema : Symbol(TSchema, Decl(deeplyNestedMappedTypes.ts, 88, 1))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 108, 33))
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 108, 61))
|
||||
>TOptional : Symbol(TOptional, Decl(deeplyNestedMappedTypes.ts, 98, 73))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 108, 33))
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 108, 61))
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 108, 61))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 108, 33))
|
||||
|
||||
export type OptionalPropertyKeys<T extends TProperties> = { [K in keyof T]: T[K] extends TOptional<TSchema> ? (T[K] extends TReadonly<T[K]> ? never : K) : never }[keyof T]
|
||||
>OptionalPropertyKeys : Symbol(OptionalPropertyKeys, Decl(deeplyNestedMappedTypes.ts, 108, 171))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 109, 33))
|
||||
>TProperties : Symbol(TProperties, Decl(deeplyNestedMappedTypes.ts, 120, 42))
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 109, 61))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 109, 33))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 109, 33))
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 109, 61))
|
||||
>TOptional : Symbol(TOptional, Decl(deeplyNestedMappedTypes.ts, 98, 73))
|
||||
>TSchema : Symbol(TSchema, Decl(deeplyNestedMappedTypes.ts, 88, 1))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 109, 33))
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 109, 61))
|
||||
>TReadonly : Symbol(TReadonly, Decl(deeplyNestedMappedTypes.ts, 97, 78))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 109, 33))
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 109, 61))
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 109, 61))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 109, 33))
|
||||
|
||||
export type RequiredPropertyKeys<T extends TProperties> = keyof Omit<T, ReadonlyOptionalPropertyKeys<T> | ReadonlyPropertyKeys<T> | OptionalPropertyKeys<T>>
|
||||
>RequiredPropertyKeys : Symbol(RequiredPropertyKeys, Decl(deeplyNestedMappedTypes.ts, 109, 171))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 110, 33))
|
||||
>TProperties : Symbol(TProperties, Decl(deeplyNestedMappedTypes.ts, 120, 42))
|
||||
>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 110, 33))
|
||||
>ReadonlyOptionalPropertyKeys : Symbol(ReadonlyOptionalPropertyKeys, Decl(deeplyNestedMappedTypes.ts, 105, 1))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 110, 33))
|
||||
>ReadonlyPropertyKeys : Symbol(ReadonlyPropertyKeys, Decl(deeplyNestedMappedTypes.ts, 107, 179))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 110, 33))
|
||||
>OptionalPropertyKeys : Symbol(OptionalPropertyKeys, Decl(deeplyNestedMappedTypes.ts, 108, 171))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 110, 33))
|
||||
|
||||
export type PropertiesReducer<T extends TProperties, R extends Record<keyof any, unknown>> = Evaluate<(
|
||||
>PropertiesReducer : Symbol(PropertiesReducer, Decl(deeplyNestedMappedTypes.ts, 110, 156))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 111, 30))
|
||||
>TProperties : Symbol(TProperties, Decl(deeplyNestedMappedTypes.ts, 120, 42))
|
||||
>R : Symbol(R, Decl(deeplyNestedMappedTypes.ts, 111, 52))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>Evaluate : Symbol(Evaluate, Decl(deeplyNestedMappedTypes.ts, 77, 1))
|
||||
|
||||
Readonly<Partial<Pick<R, ReadonlyOptionalPropertyKeys<T>>>> &
|
||||
>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --))
|
||||
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
|
||||
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
|
||||
>R : Symbol(R, Decl(deeplyNestedMappedTypes.ts, 111, 52))
|
||||
>ReadonlyOptionalPropertyKeys : Symbol(ReadonlyOptionalPropertyKeys, Decl(deeplyNestedMappedTypes.ts, 105, 1))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 111, 30))
|
||||
|
||||
Readonly<Pick<R, ReadonlyPropertyKeys<T>>> &
|
||||
>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --))
|
||||
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
|
||||
>R : Symbol(R, Decl(deeplyNestedMappedTypes.ts, 111, 52))
|
||||
>ReadonlyPropertyKeys : Symbol(ReadonlyPropertyKeys, Decl(deeplyNestedMappedTypes.ts, 107, 179))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 111, 30))
|
||||
|
||||
Partial<Pick<R, OptionalPropertyKeys<T>>> &
|
||||
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
|
||||
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
|
||||
>R : Symbol(R, Decl(deeplyNestedMappedTypes.ts, 111, 52))
|
||||
>OptionalPropertyKeys : Symbol(OptionalPropertyKeys, Decl(deeplyNestedMappedTypes.ts, 108, 171))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 111, 30))
|
||||
|
||||
Required<Pick<R, RequiredPropertyKeys<T>>>
|
||||
>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --))
|
||||
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
|
||||
>R : Symbol(R, Decl(deeplyNestedMappedTypes.ts, 111, 52))
|
||||
>RequiredPropertyKeys : Symbol(RequiredPropertyKeys, Decl(deeplyNestedMappedTypes.ts, 109, 171))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 111, 30))
|
||||
|
||||
)>
|
||||
export type PropertiesReduce<T extends TProperties, P extends unknown[]> = PropertiesReducer<T, {
|
||||
>PropertiesReduce : Symbol(PropertiesReduce, Decl(deeplyNestedMappedTypes.ts, 116, 2))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 117, 29))
|
||||
>TProperties : Symbol(TProperties, Decl(deeplyNestedMappedTypes.ts, 120, 42))
|
||||
>P : Symbol(P, Decl(deeplyNestedMappedTypes.ts, 117, 51))
|
||||
>PropertiesReducer : Symbol(PropertiesReducer, Decl(deeplyNestedMappedTypes.ts, 110, 156))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 117, 29))
|
||||
|
||||
[K in keyof T]: Static<T[K], P>
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 118, 5))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 117, 29))
|
||||
>Static : Symbol(Static, Decl(deeplyNestedMappedTypes.ts, 127, 1))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 117, 29))
|
||||
>K : Symbol(K, Decl(deeplyNestedMappedTypes.ts, 118, 5))
|
||||
>P : Symbol(P, Decl(deeplyNestedMappedTypes.ts, 117, 51))
|
||||
|
||||
}>
|
||||
export type TPropertyKey = string | number
|
||||
>TPropertyKey : Symbol(TPropertyKey, Decl(deeplyNestedMappedTypes.ts, 119, 2))
|
||||
|
||||
export type TProperties = Record<TPropertyKey, TSchema>
|
||||
>TProperties : Symbol(TProperties, Decl(deeplyNestedMappedTypes.ts, 120, 42))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>TPropertyKey : Symbol(TPropertyKey, Decl(deeplyNestedMappedTypes.ts, 119, 2))
|
||||
>TSchema : Symbol(TSchema, Decl(deeplyNestedMappedTypes.ts, 88, 1))
|
||||
|
||||
export interface TObject<T extends TProperties = TProperties> extends TSchema {
|
||||
>TObject : Symbol(TObject, Decl(deeplyNestedMappedTypes.ts, 121, 55))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 122, 25))
|
||||
>TProperties : Symbol(TProperties, Decl(deeplyNestedMappedTypes.ts, 120, 42))
|
||||
>TProperties : Symbol(TProperties, Decl(deeplyNestedMappedTypes.ts, 120, 42))
|
||||
>TSchema : Symbol(TSchema, Decl(deeplyNestedMappedTypes.ts, 88, 1))
|
||||
|
||||
[Kind]: 'Object'
|
||||
>[Kind] : Symbol(TObject[Kind], Decl(deeplyNestedMappedTypes.ts, 122, 79))
|
||||
>Kind : Symbol(Kind, Decl(deeplyNestedMappedTypes.ts, 84, 20))
|
||||
|
||||
static: PropertiesReduce<T, this['params']>
|
||||
>static : Symbol(TObject.static, Decl(deeplyNestedMappedTypes.ts, 123, 20))
|
||||
>PropertiesReduce : Symbol(PropertiesReduce, Decl(deeplyNestedMappedTypes.ts, 116, 2))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 122, 25))
|
||||
|
||||
type: 'object'
|
||||
>type : Symbol(TObject.type, Decl(deeplyNestedMappedTypes.ts, 124, 47))
|
||||
|
||||
properties: T
|
||||
>properties : Symbol(TObject.properties, Decl(deeplyNestedMappedTypes.ts, 125, 18))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 122, 25))
|
||||
}
|
||||
|
||||
export type Static<T extends TSchema, P extends unknown[] = []> = (T & { params: P; })['static']
|
||||
>Static : Symbol(Static, Decl(deeplyNestedMappedTypes.ts, 127, 1))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 129, 19))
|
||||
>TSchema : Symbol(TSchema, Decl(deeplyNestedMappedTypes.ts, 88, 1))
|
||||
>P : Symbol(P, Decl(deeplyNestedMappedTypes.ts, 129, 37))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 129, 19))
|
||||
>params : Symbol(params, Decl(deeplyNestedMappedTypes.ts, 129, 72))
|
||||
>P : Symbol(P, Decl(deeplyNestedMappedTypes.ts, 129, 37))
|
||||
|
||||
declare namespace Type {
|
||||
>Type : Symbol(Type, Decl(deeplyNestedMappedTypes.ts, 129, 96))
|
||||
|
||||
function Object<T extends TProperties>(object: T): TObject<T>
|
||||
>Object : Symbol(Object, Decl(deeplyNestedMappedTypes.ts, 131, 24))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 132, 20))
|
||||
>TProperties : Symbol(TProperties, Decl(deeplyNestedMappedTypes.ts, 120, 42))
|
||||
>object : Symbol(object, Decl(deeplyNestedMappedTypes.ts, 132, 43))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 132, 20))
|
||||
>TObject : Symbol(TObject, Decl(deeplyNestedMappedTypes.ts, 121, 55))
|
||||
>T : Symbol(T, Decl(deeplyNestedMappedTypes.ts, 132, 20))
|
||||
|
||||
function String(): TString
|
||||
>String : Symbol(String, Decl(deeplyNestedMappedTypes.ts, 132, 65))
|
||||
>TString : Symbol(TString, Decl(deeplyNestedMappedTypes.ts, 99, 73))
|
||||
}
|
||||
|
||||
|
||||
@ -125,3 +125,243 @@ const bar2: Bar2 = bar1; // Error expected
|
||||
>bar2 : { x: { y: { z: { a: { b: Record<"c", string>; }; }; }; }; }
|
||||
>bar1 : { x: { y: { z: { a: { b: Record<"c", number>; }; }; }; }; }
|
||||
|
||||
// Repro from #56138
|
||||
|
||||
export type Input = Static<typeof Input>
|
||||
>Input : { level1: { level2: { foo: string; }; }; }
|
||||
>Input : TObject<{ level1: TObject<{ level2: TObject<{ foo: TString; }>; }>; }>
|
||||
|
||||
export const Input = Type.Object({
|
||||
>Input : TObject<{ level1: TObject<{ level2: TObject<{ foo: TString; }>; }>; }>
|
||||
>Type.Object({ level1: Type.Object({ level2: Type.Object({ foo: Type.String(), }) })}) : TObject<{ level1: TObject<{ level2: TObject<{ foo: TString; }>; }>; }>
|
||||
>Type.Object : <T extends TProperties>(object: T) => TObject<T>
|
||||
>Type : typeof Type
|
||||
>Object : <T extends TProperties>(object: T) => TObject<T>
|
||||
>{ level1: Type.Object({ level2: Type.Object({ foo: Type.String(), }) })} : { level1: TObject<{ level2: TObject<{ foo: TString; }>; }>; }
|
||||
|
||||
level1: Type.Object({
|
||||
>level1 : TObject<{ level2: TObject<{ foo: TString; }>; }>
|
||||
>Type.Object({ level2: Type.Object({ foo: Type.String(), }) }) : TObject<{ level2: TObject<{ foo: TString; }>; }>
|
||||
>Type.Object : <T extends TProperties>(object: T) => TObject<T>
|
||||
>Type : typeof Type
|
||||
>Object : <T extends TProperties>(object: T) => TObject<T>
|
||||
>{ level2: Type.Object({ foo: Type.String(), }) } : { level2: TObject<{ foo: TString; }>; }
|
||||
|
||||
level2: Type.Object({
|
||||
>level2 : TObject<{ foo: TString; }>
|
||||
>Type.Object({ foo: Type.String(), }) : TObject<{ foo: TString; }>
|
||||
>Type.Object : <T extends TProperties>(object: T) => TObject<T>
|
||||
>Type : typeof Type
|
||||
>Object : <T extends TProperties>(object: T) => TObject<T>
|
||||
>{ foo: Type.String(), } : { foo: TString; }
|
||||
|
||||
foo: Type.String(),
|
||||
>foo : TString
|
||||
>Type.String() : TString
|
||||
>Type.String : () => TString
|
||||
>Type : typeof Type
|
||||
>String : () => TString
|
||||
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
export type Output = Static<typeof Output>
|
||||
>Output : { level1: { level2: { foo: string; bar: string; }; }; }
|
||||
>Output : TObject<{ level1: TObject<{ level2: TObject<{ foo: TString; bar: TString; }>; }>; }>
|
||||
|
||||
export const Output = Type.Object({
|
||||
>Output : TObject<{ level1: TObject<{ level2: TObject<{ foo: TString; bar: TString; }>; }>; }>
|
||||
>Type.Object({ level1: Type.Object({ level2: Type.Object({ foo: Type.String(), bar: Type.String(), }) })}) : TObject<{ level1: TObject<{ level2: TObject<{ foo: TString; bar: TString; }>; }>; }>
|
||||
>Type.Object : <T extends TProperties>(object: T) => TObject<T>
|
||||
>Type : typeof Type
|
||||
>Object : <T extends TProperties>(object: T) => TObject<T>
|
||||
>{ level1: Type.Object({ level2: Type.Object({ foo: Type.String(), bar: Type.String(), }) })} : { level1: TObject<{ level2: TObject<{ foo: TString; bar: TString; }>; }>; }
|
||||
|
||||
level1: Type.Object({
|
||||
>level1 : TObject<{ level2: TObject<{ foo: TString; bar: TString; }>; }>
|
||||
>Type.Object({ level2: Type.Object({ foo: Type.String(), bar: Type.String(), }) }) : TObject<{ level2: TObject<{ foo: TString; bar: TString; }>; }>
|
||||
>Type.Object : <T extends TProperties>(object: T) => TObject<T>
|
||||
>Type : typeof Type
|
||||
>Object : <T extends TProperties>(object: T) => TObject<T>
|
||||
>{ level2: Type.Object({ foo: Type.String(), bar: Type.String(), }) } : { level2: TObject<{ foo: TString; bar: TString; }>; }
|
||||
|
||||
level2: Type.Object({
|
||||
>level2 : TObject<{ foo: TString; bar: TString; }>
|
||||
>Type.Object({ foo: Type.String(), bar: Type.String(), }) : TObject<{ foo: TString; bar: TString; }>
|
||||
>Type.Object : <T extends TProperties>(object: T) => TObject<T>
|
||||
>Type : typeof Type
|
||||
>Object : <T extends TProperties>(object: T) => TObject<T>
|
||||
>{ foo: Type.String(), bar: Type.String(), } : { foo: TString; bar: TString; }
|
||||
|
||||
foo: Type.String(),
|
||||
>foo : TString
|
||||
>Type.String() : TString
|
||||
>Type.String : () => TString
|
||||
>Type : typeof Type
|
||||
>String : () => TString
|
||||
|
||||
bar: Type.String(),
|
||||
>bar : TString
|
||||
>Type.String() : TString
|
||||
>Type.String : () => TString
|
||||
>Type : typeof Type
|
||||
>String : () => TString
|
||||
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function problematicFunction1(ors: Input[]): Output[] {
|
||||
>problematicFunction1 : (ors: Input[]) => Output[]
|
||||
>ors : { level1: { level2: { foo: string; }; }; }[]
|
||||
|
||||
return ors; // Error
|
||||
>ors : { level1: { level2: { foo: string; }; }; }[]
|
||||
}
|
||||
|
||||
function problematicFunction2<T extends Output[]>(ors: Input[]): T {
|
||||
>problematicFunction2 : <T extends { level1: { level2: { foo: string; bar: string; }; }; }[]>(ors: Input[]) => T
|
||||
>ors : { level1: { level2: { foo: string; }; }; }[]
|
||||
|
||||
return ors; // Error
|
||||
>ors : { level1: { level2: { foo: string; }; }; }[]
|
||||
}
|
||||
|
||||
function problematicFunction3(ors: (typeof Input.static)[]): Output[] {
|
||||
>problematicFunction3 : (ors: (typeof Input.static)[]) => Output[]
|
||||
>ors : { level1: { level2: { foo: string; }; }; }[]
|
||||
>Input.static : { level1: { level2: { foo: string; }; }; }
|
||||
>Input : TObject<{ level1: TObject<{ level2: TObject<{ foo: TString; }>; }>; }>
|
||||
>static : { level1: { level2: { foo: string; }; }; }
|
||||
|
||||
return ors; // Error
|
||||
>ors : { level1: { level2: { foo: string; }; }; }[]
|
||||
}
|
||||
|
||||
export type Evaluate<T> = T extends infer O ? { [K in keyof O]: O[K] } : never
|
||||
>Evaluate : Evaluate<T>
|
||||
|
||||
export declare const Readonly: unique symbol;
|
||||
>Readonly : unique symbol
|
||||
|
||||
export declare const Optional: unique symbol;
|
||||
>Optional : unique symbol
|
||||
|
||||
export declare const Hint: unique symbol;
|
||||
>Hint : unique symbol
|
||||
|
||||
export declare const Kind: unique symbol;
|
||||
>Kind : unique symbol
|
||||
|
||||
export interface TKind {
|
||||
[Kind]: string
|
||||
>[Kind] : string
|
||||
>Kind : unique symbol
|
||||
}
|
||||
export interface TSchema extends TKind {
|
||||
[Readonly]?: string
|
||||
>[Readonly] : string | undefined
|
||||
>Readonly : unique symbol
|
||||
|
||||
[Optional]?: string
|
||||
>[Optional] : string | undefined
|
||||
>Optional : unique symbol
|
||||
|
||||
[Hint]?: string
|
||||
>[Hint] : string | undefined
|
||||
>Hint : unique symbol
|
||||
|
||||
params: unknown[]
|
||||
>params : unknown[]
|
||||
|
||||
static: unknown
|
||||
>static : unknown
|
||||
}
|
||||
|
||||
export type TReadonlyOptional<T extends TSchema> = TOptional<T> & TReadonly<T>
|
||||
>TReadonlyOptional : TReadonlyOptional<T>
|
||||
|
||||
export type TReadonly<T extends TSchema> = T & { [Readonly]: 'Readonly' }
|
||||
>TReadonly : TReadonly<T>
|
||||
>[Readonly] : "Readonly"
|
||||
>Readonly : unique symbol
|
||||
|
||||
export type TOptional<T extends TSchema> = T & { [Optional]: 'Optional' }
|
||||
>TOptional : TOptional<T>
|
||||
>[Optional] : "Optional"
|
||||
>Optional : unique symbol
|
||||
|
||||
export interface TString extends TSchema {
|
||||
[Kind]: 'String';
|
||||
>[Kind] : "String"
|
||||
>Kind : unique symbol
|
||||
|
||||
static: string;
|
||||
>static : string
|
||||
|
||||
type: 'string';
|
||||
>type : "string"
|
||||
}
|
||||
|
||||
export type ReadonlyOptionalPropertyKeys<T extends TProperties> = { [K in keyof T]: T[K] extends TReadonly<TSchema> ? (T[K] extends TOptional<T[K]> ? K : never) : never }[keyof T]
|
||||
>ReadonlyOptionalPropertyKeys : ReadonlyOptionalPropertyKeys<T>
|
||||
|
||||
export type ReadonlyPropertyKeys<T extends TProperties> = { [K in keyof T]: T[K] extends TReadonly<TSchema> ? (T[K] extends TOptional<T[K]> ? never : K) : never }[keyof T]
|
||||
>ReadonlyPropertyKeys : ReadonlyPropertyKeys<T>
|
||||
|
||||
export type OptionalPropertyKeys<T extends TProperties> = { [K in keyof T]: T[K] extends TOptional<TSchema> ? (T[K] extends TReadonly<T[K]> ? never : K) : never }[keyof T]
|
||||
>OptionalPropertyKeys : OptionalPropertyKeys<T>
|
||||
|
||||
export type RequiredPropertyKeys<T extends TProperties> = keyof Omit<T, ReadonlyOptionalPropertyKeys<T> | ReadonlyPropertyKeys<T> | OptionalPropertyKeys<T>>
|
||||
>RequiredPropertyKeys : Exclude<keyof T, ReadonlyOptionalPropertyKeys<T> | ReadonlyPropertyKeys<T> | OptionalPropertyKeys<T>>
|
||||
|
||||
export type PropertiesReducer<T extends TProperties, R extends Record<keyof any, unknown>> = Evaluate<(
|
||||
>PropertiesReducer : PropertiesReducer<T, R>
|
||||
|
||||
Readonly<Partial<Pick<R, ReadonlyOptionalPropertyKeys<T>>>> &
|
||||
Readonly<Pick<R, ReadonlyPropertyKeys<T>>> &
|
||||
Partial<Pick<R, OptionalPropertyKeys<T>>> &
|
||||
Required<Pick<R, RequiredPropertyKeys<T>>>
|
||||
)>
|
||||
export type PropertiesReduce<T extends TProperties, P extends unknown[]> = PropertiesReducer<T, {
|
||||
>PropertiesReduce : PropertiesReduce<T, P>
|
||||
|
||||
[K in keyof T]: Static<T[K], P>
|
||||
}>
|
||||
export type TPropertyKey = string | number
|
||||
>TPropertyKey : string | number
|
||||
|
||||
export type TProperties = Record<TPropertyKey, TSchema>
|
||||
>TProperties : { [x: string]: TSchema; [x: number]: TSchema; }
|
||||
|
||||
export interface TObject<T extends TProperties = TProperties> extends TSchema {
|
||||
[Kind]: 'Object'
|
||||
>[Kind] : "Object"
|
||||
>Kind : unique symbol
|
||||
|
||||
static: PropertiesReduce<T, this['params']>
|
||||
>static : Evaluate<Readonly<Partial<Pick<{ [K in keyof T]: Static<T[K], this["params"]>; }, ReadonlyOptionalPropertyKeys<T>>>> & Readonly<Pick<{ [K in keyof T]: Static<T[K], this["params"]>; }, ReadonlyPropertyKeys<T>>> & Partial<Pick<{ [K in keyof T]: Static<T[K], this["params"]>; }, OptionalPropertyKeys<T>>> & Required<Pick<{ [K in keyof T]: Static<T[K], this["params"]>; }, Exclude<keyof T, ReadonlyOptionalPropertyKeys<T> | ReadonlyPropertyKeys<T> | OptionalPropertyKeys<T>>>>>
|
||||
|
||||
type: 'object'
|
||||
>type : "object"
|
||||
|
||||
properties: T
|
||||
>properties : T
|
||||
}
|
||||
|
||||
export type Static<T extends TSchema, P extends unknown[] = []> = (T & { params: P; })['static']
|
||||
>Static : Static<T, P>
|
||||
>params : P
|
||||
|
||||
declare namespace Type {
|
||||
>Type : typeof Type
|
||||
|
||||
function Object<T extends TProperties>(object: T): TObject<T>
|
||||
>Object : <T extends TProperties>(object: T) => TObject<T>
|
||||
>object : T
|
||||
|
||||
function String(): TString
|
||||
>String : () => TString
|
||||
}
|
||||
|
||||
|
||||
@ -46,3 +46,93 @@ type Bar2 = NestedRecord<"x.y.z.a.b.c", string>;
|
||||
|
||||
declare const bar1: Bar1;
|
||||
const bar2: Bar2 = bar1; // Error expected
|
||||
|
||||
// Repro from #56138
|
||||
|
||||
export type Input = Static<typeof Input>
|
||||
export const Input = Type.Object({
|
||||
level1: Type.Object({
|
||||
level2: Type.Object({
|
||||
foo: Type.String(),
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
export type Output = Static<typeof Output>
|
||||
export const Output = Type.Object({
|
||||
level1: Type.Object({
|
||||
level2: Type.Object({
|
||||
foo: Type.String(),
|
||||
bar: Type.String(),
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function problematicFunction1(ors: Input[]): Output[] {
|
||||
return ors; // Error
|
||||
}
|
||||
|
||||
function problematicFunction2<T extends Output[]>(ors: Input[]): T {
|
||||
return ors; // Error
|
||||
}
|
||||
|
||||
function problematicFunction3(ors: (typeof Input.static)[]): Output[] {
|
||||
return ors; // Error
|
||||
}
|
||||
|
||||
export type Evaluate<T> = T extends infer O ? { [K in keyof O]: O[K] } : never
|
||||
|
||||
export declare const Readonly: unique symbol;
|
||||
export declare const Optional: unique symbol;
|
||||
export declare const Hint: unique symbol;
|
||||
export declare const Kind: unique symbol;
|
||||
|
||||
export interface TKind {
|
||||
[Kind]: string
|
||||
}
|
||||
export interface TSchema extends TKind {
|
||||
[Readonly]?: string
|
||||
[Optional]?: string
|
||||
[Hint]?: string
|
||||
params: unknown[]
|
||||
static: unknown
|
||||
}
|
||||
|
||||
export type TReadonlyOptional<T extends TSchema> = TOptional<T> & TReadonly<T>
|
||||
export type TReadonly<T extends TSchema> = T & { [Readonly]: 'Readonly' }
|
||||
export type TOptional<T extends TSchema> = T & { [Optional]: 'Optional' }
|
||||
|
||||
export interface TString extends TSchema {
|
||||
[Kind]: 'String';
|
||||
static: string;
|
||||
type: 'string';
|
||||
}
|
||||
|
||||
export type ReadonlyOptionalPropertyKeys<T extends TProperties> = { [K in keyof T]: T[K] extends TReadonly<TSchema> ? (T[K] extends TOptional<T[K]> ? K : never) : never }[keyof T]
|
||||
export type ReadonlyPropertyKeys<T extends TProperties> = { [K in keyof T]: T[K] extends TReadonly<TSchema> ? (T[K] extends TOptional<T[K]> ? never : K) : never }[keyof T]
|
||||
export type OptionalPropertyKeys<T extends TProperties> = { [K in keyof T]: T[K] extends TOptional<TSchema> ? (T[K] extends TReadonly<T[K]> ? never : K) : never }[keyof T]
|
||||
export type RequiredPropertyKeys<T extends TProperties> = keyof Omit<T, ReadonlyOptionalPropertyKeys<T> | ReadonlyPropertyKeys<T> | OptionalPropertyKeys<T>>
|
||||
export type PropertiesReducer<T extends TProperties, R extends Record<keyof any, unknown>> = Evaluate<(
|
||||
Readonly<Partial<Pick<R, ReadonlyOptionalPropertyKeys<T>>>> &
|
||||
Readonly<Pick<R, ReadonlyPropertyKeys<T>>> &
|
||||
Partial<Pick<R, OptionalPropertyKeys<T>>> &
|
||||
Required<Pick<R, RequiredPropertyKeys<T>>>
|
||||
)>
|
||||
export type PropertiesReduce<T extends TProperties, P extends unknown[]> = PropertiesReducer<T, {
|
||||
[K in keyof T]: Static<T[K], P>
|
||||
}>
|
||||
export type TPropertyKey = string | number
|
||||
export type TProperties = Record<TPropertyKey, TSchema>
|
||||
export interface TObject<T extends TProperties = TProperties> extends TSchema {
|
||||
[Kind]: 'Object'
|
||||
static: PropertiesReduce<T, this['params']>
|
||||
type: 'object'
|
||||
properties: T
|
||||
}
|
||||
|
||||
export type Static<T extends TSchema, P extends unknown[] = []> = (T & { params: P; })['static']
|
||||
|
||||
declare namespace Type {
|
||||
function Object<T extends TProperties>(object: T): TObject<T>
|
||||
function String(): TString
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user