diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8e5c03560db3e..a0c55efbaf560 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26436,7 +26436,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const templateType = getTemplateTypeFromMappedType(target); const inference = createInferenceInfo(typeParameter); inferTypes([inference], sourceType, templateType); - return getTypeFromInference(inference) || unknownType; + return getWidenedType(getTypeFromInference(inference) || unknownType); } function inferReverseMappedType(source: Type, target: MappedType, constraint: IndexType): Type | undefined { diff --git a/tests/baselines/reference/reverseMappedTypeInferenceWidening1.symbols b/tests/baselines/reference/reverseMappedTypeInferenceWidening1.symbols new file mode 100644 index 0000000000000..635dcd0afed7d --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeInferenceWidening1.symbols @@ -0,0 +1,181 @@ +//// [tests/cases/compiler/reverseMappedTypeInferenceWidening1.ts] //// + +=== reverseMappedTypeInferenceWidening1.ts === +// https://github.com/microsoft/TypeScript/issues/62720 + +type TypeFunction = (...args: any[]) => ReturnType; +>TypeFunction : Symbol(TypeFunction, Decl(reverseMappedTypeInferenceWidening1.ts, 0, 0)) +>ReturnType : Symbol(ReturnType, Decl(reverseMappedTypeInferenceWidening1.ts, 2, 18)) +>args : Symbol(args, Decl(reverseMappedTypeInferenceWidening1.ts, 2, 43)) +>ReturnType : Symbol(ReturnType, Decl(reverseMappedTypeInferenceWidening1.ts, 2, 18)) + +type Flags = { +>Flags : Symbol(Flags, Decl(reverseMappedTypeInferenceWidening1.ts, 2, 73)) + + [flagName: string]: { +>flagName : Symbol(flagName, Decl(reverseMappedTypeInferenceWidening1.ts, 4, 3)) + + type: TypeFunction; +>type : Symbol(type, Decl(reverseMappedTypeInferenceWidening1.ts, 4, 23)) +>TypeFunction : Symbol(TypeFunction, Decl(reverseMappedTypeInferenceWidening1.ts, 0, 0)) + + default?: unknown; +>default : Symbol(default, Decl(reverseMappedTypeInferenceWidening1.ts, 5, 23)) + + }; +}; +type TypeFlag = { +>TypeFlag : Symbol(TypeFlag, Decl(reverseMappedTypeInferenceWidening1.ts, 8, 2)) +>Schemas : Symbol(Schemas, Decl(reverseMappedTypeInferenceWidening1.ts, 9, 14)) +>Flags : Symbol(Flags, Decl(reverseMappedTypeInferenceWidening1.ts, 2, 73)) + + [flag in keyof Schemas]: Schemas[flag] extends { type: TypeFunction } +>flag : Symbol(flag, Decl(reverseMappedTypeInferenceWidening1.ts, 10, 3)) +>Schemas : Symbol(Schemas, Decl(reverseMappedTypeInferenceWidening1.ts, 9, 14)) +>Schemas : Symbol(Schemas, Decl(reverseMappedTypeInferenceWidening1.ts, 9, 14)) +>flag : Symbol(flag, Decl(reverseMappedTypeInferenceWidening1.ts, 10, 3)) +>type : Symbol(type, Decl(reverseMappedTypeInferenceWidening1.ts, 10, 50)) +>TypeFunction : Symbol(TypeFunction, Decl(reverseMappedTypeInferenceWidening1.ts, 0, 0)) +>T : Symbol(T, Decl(reverseMappedTypeInferenceWidening1.ts, 10, 75)) + + ? T +>T : Symbol(T, Decl(reverseMappedTypeInferenceWidening1.ts, 10, 75)) + + : never; +}; + +declare function fn1( +>fn1 : Symbol(fn1, Decl(reverseMappedTypeInferenceWidening1.ts, 13, 2)) +>Options : Symbol(Options, Decl(reverseMappedTypeInferenceWidening1.ts, 15, 21)) +>Flags : Symbol(Flags, Decl(reverseMappedTypeInferenceWidening1.ts, 2, 73)) + + options: Options, +>options : Symbol(options, Decl(reverseMappedTypeInferenceWidening1.ts, 15, 44)) +>Options : Symbol(Options, Decl(reverseMappedTypeInferenceWidening1.ts, 15, 21)) + +): TypeFlag; +>TypeFlag : Symbol(TypeFlag, Decl(reverseMappedTypeInferenceWidening1.ts, 8, 2)) +>Options : Symbol(Options, Decl(reverseMappedTypeInferenceWidening1.ts, 15, 21)) + +const result1 = fn1({ +>result1 : Symbol(result1, Decl(reverseMappedTypeInferenceWidening1.ts, 19, 5)) +>fn1 : Symbol(fn1, Decl(reverseMappedTypeInferenceWidening1.ts, 13, 2)) + + booleanFlag: { type: Boolean }, +>booleanFlag : Symbol(booleanFlag, Decl(reverseMappedTypeInferenceWidening1.ts, 19, 21)) +>type : Symbol(type, Decl(reverseMappedTypeInferenceWidening1.ts, 20, 16)) +>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + + booleanFlagDefault: { +>booleanFlagDefault : Symbol(booleanFlagDefault, Decl(reverseMappedTypeInferenceWidening1.ts, 20, 33)) + + type: Boolean, +>type : Symbol(type, Decl(reverseMappedTypeInferenceWidening1.ts, 21, 23)) +>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + + default: false, +>default : Symbol(default, Decl(reverseMappedTypeInferenceWidening1.ts, 22, 18)) + + }, +}); +result1.booleanFlag; // boolean +>result1.booleanFlag : Symbol(booleanFlag, Decl(reverseMappedTypeInferenceWidening1.ts, 19, 21)) +>result1 : Symbol(result1, Decl(reverseMappedTypeInferenceWidening1.ts, 19, 5)) +>booleanFlag : Symbol(booleanFlag, Decl(reverseMappedTypeInferenceWidening1.ts, 19, 21)) + +result1.booleanFlagDefault; // boolean +>result1.booleanFlagDefault : Symbol(booleanFlagDefault, Decl(reverseMappedTypeInferenceWidening1.ts, 20, 33)) +>result1 : Symbol(result1, Decl(reverseMappedTypeInferenceWidening1.ts, 19, 5)) +>booleanFlagDefault : Symbol(booleanFlagDefault, Decl(reverseMappedTypeInferenceWidening1.ts, 20, 33)) + +declare function fn2( +>fn2 : Symbol(fn2, Decl(reverseMappedTypeInferenceWidening1.ts, 27, 27)) +>Options : Symbol(Options, Decl(reverseMappedTypeInferenceWidening1.ts, 29, 21)) +>Flags : Symbol(Flags, Decl(reverseMappedTypeInferenceWidening1.ts, 2, 73)) + + options: Readonly, +>options : Symbol(options, Decl(reverseMappedTypeInferenceWidening1.ts, 29, 44)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>Options : Symbol(Options, Decl(reverseMappedTypeInferenceWidening1.ts, 29, 21)) + +): TypeFlag; +>TypeFlag : Symbol(TypeFlag, Decl(reverseMappedTypeInferenceWidening1.ts, 8, 2)) +>Options : Symbol(Options, Decl(reverseMappedTypeInferenceWidening1.ts, 29, 21)) + +const result2 = fn2({ +>result2 : Symbol(result2, Decl(reverseMappedTypeInferenceWidening1.ts, 33, 5)) +>fn2 : Symbol(fn2, Decl(reverseMappedTypeInferenceWidening1.ts, 27, 27)) + + booleanFlag: { type: Boolean }, +>booleanFlag : Symbol(booleanFlag, Decl(reverseMappedTypeInferenceWidening1.ts, 33, 21)) +>type : Symbol(type, Decl(reverseMappedTypeInferenceWidening1.ts, 34, 16)) +>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + + booleanFlagDefault: { +>booleanFlagDefault : Symbol(booleanFlagDefault, Decl(reverseMappedTypeInferenceWidening1.ts, 34, 33)) + + type: Boolean, +>type : Symbol(type, Decl(reverseMappedTypeInferenceWidening1.ts, 35, 23)) +>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + + default: false, +>default : Symbol(default, Decl(reverseMappedTypeInferenceWidening1.ts, 36, 18)) + + }, +}); +result2.booleanFlag; // boolean +>result2.booleanFlag : Symbol(booleanFlag, Decl(reverseMappedTypeInferenceWidening1.ts, 33, 21)) +>result2 : Symbol(result2, Decl(reverseMappedTypeInferenceWidening1.ts, 33, 5)) +>booleanFlag : Symbol(booleanFlag, Decl(reverseMappedTypeInferenceWidening1.ts, 33, 21)) + +result2.booleanFlagDefault; // boolean +>result2.booleanFlagDefault : Symbol(booleanFlagDefault, Decl(reverseMappedTypeInferenceWidening1.ts, 34, 33)) +>result2 : Symbol(result2, Decl(reverseMappedTypeInferenceWidening1.ts, 33, 5)) +>booleanFlagDefault : Symbol(booleanFlagDefault, Decl(reverseMappedTypeInferenceWidening1.ts, 34, 33)) + +declare function fn3( +>fn3 : Symbol(fn3, Decl(reverseMappedTypeInferenceWidening1.ts, 41, 27)) +>Options : Symbol(Options, Decl(reverseMappedTypeInferenceWidening1.ts, 43, 21)) +>Flags : Symbol(Flags, Decl(reverseMappedTypeInferenceWidening1.ts, 2, 73)) + + options: Readonly, +>options : Symbol(options, Decl(reverseMappedTypeInferenceWidening1.ts, 43, 44)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>Options : Symbol(Options, Decl(reverseMappedTypeInferenceWidening1.ts, 43, 21)) + +): Options; +>Options : Symbol(Options, Decl(reverseMappedTypeInferenceWidening1.ts, 43, 21)) + +const result3 = fn3({ +>result3 : Symbol(result3, Decl(reverseMappedTypeInferenceWidening1.ts, 47, 5)) +>fn3 : Symbol(fn3, Decl(reverseMappedTypeInferenceWidening1.ts, 41, 27)) + + booleanFlag: { type: Boolean }, +>booleanFlag : Symbol(booleanFlag, Decl(reverseMappedTypeInferenceWidening1.ts, 47, 21)) +>type : Symbol(type, Decl(reverseMappedTypeInferenceWidening1.ts, 48, 16)) +>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + + booleanFlagDefault: { +>booleanFlagDefault : Symbol(booleanFlagDefault, Decl(reverseMappedTypeInferenceWidening1.ts, 48, 33)) + + type: Boolean, +>type : Symbol(type, Decl(reverseMappedTypeInferenceWidening1.ts, 49, 23)) +>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + + default: false, // no cursed EPC failure here +>default : Symbol(default, Decl(reverseMappedTypeInferenceWidening1.ts, 50, 18)) + + }, +}); + +declare function takeType(arg: { type: unknown }): void; +>takeType : Symbol(takeType, Decl(reverseMappedTypeInferenceWidening1.ts, 53, 3)) +>arg : Symbol(arg, Decl(reverseMappedTypeInferenceWidening1.ts, 55, 26)) +>type : Symbol(type, Decl(reverseMappedTypeInferenceWidening1.ts, 55, 32)) + +takeType(result3.booleanFlagDefault); +>takeType : Symbol(takeType, Decl(reverseMappedTypeInferenceWidening1.ts, 53, 3)) +>result3.booleanFlagDefault : Symbol(booleanFlagDefault, Decl(reverseMappedTypeInferenceWidening1.ts, 48, 33)) +>result3 : Symbol(result3, Decl(reverseMappedTypeInferenceWidening1.ts, 47, 5)) +>booleanFlagDefault : Symbol(booleanFlagDefault, Decl(reverseMappedTypeInferenceWidening1.ts, 48, 33)) + diff --git a/tests/baselines/reference/reverseMappedTypeInferenceWidening1.types b/tests/baselines/reference/reverseMappedTypeInferenceWidening1.types new file mode 100644 index 0000000000000..f8001f76ebe68 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeInferenceWidening1.types @@ -0,0 +1,244 @@ +//// [tests/cases/compiler/reverseMappedTypeInferenceWidening1.ts] //// + +=== reverseMappedTypeInferenceWidening1.ts === +// https://github.com/microsoft/TypeScript/issues/62720 + +type TypeFunction = (...args: any[]) => ReturnType; +>TypeFunction : TypeFunction +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>args : any[] +> : ^^^^^ + +type Flags = { +>Flags : Flags +> : ^^^^^ + + [flagName: string]: { +>flagName : string +> : ^^^^^^ + + type: TypeFunction; +>type : TypeFunction +> : ^^^^^^^^^^^^^^^^^^^^^ + + default?: unknown; +>default : unknown +> : ^^^^^^^ + + }; +}; +type TypeFlag = { +>TypeFlag : TypeFlag +> : ^^^^^^^^^^^^^^^^^ + + [flag in keyof Schemas]: Schemas[flag] extends { type: TypeFunction } +>type : TypeFunction +> : ^^^^^^^^^^^^^^^ + + ? T + : never; +}; + +declare function fn1( +>fn1 : (options: Options) => TypeFlag +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ + + options: Options, +>options : Options +> : ^^^^^^^ + +): TypeFlag; + +const result1 = fn1({ +>result1 : TypeFlag<{ booleanFlag: { type: BooleanConstructor; }; booleanFlagDefault: { type: BooleanConstructor; default: boolean; }; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>fn1({ booleanFlag: { type: Boolean }, booleanFlagDefault: { type: Boolean, default: false, },}) : TypeFlag<{ booleanFlag: { type: BooleanConstructor; }; booleanFlagDefault: { type: BooleanConstructor; default: boolean; }; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>fn1 : (options: Options) => TypeFlag +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ booleanFlag: { type: Boolean }, booleanFlagDefault: { type: Boolean, default: false, },} : { booleanFlag: { type: BooleanConstructor; }; booleanFlagDefault: { type: BooleanConstructor; default: false; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + booleanFlag: { type: Boolean }, +>booleanFlag : { type: BooleanConstructor; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ type: Boolean } : { type: BooleanConstructor; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : BooleanConstructor +> : ^^^^^^^^^^^^^^^^^^ +>Boolean : BooleanConstructor +> : ^^^^^^^^^^^^^^^^^^ + + booleanFlagDefault: { +>booleanFlagDefault : { type: BooleanConstructor; default: false; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ type: Boolean, default: false, } : { type: BooleanConstructor; default: false; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + type: Boolean, +>type : BooleanConstructor +> : ^^^^^^^^^^^^^^^^^^ +>Boolean : BooleanConstructor +> : ^^^^^^^^^^^^^^^^^^ + + default: false, +>default : false +> : ^^^^^ +>false : false +> : ^^^^^ + + }, +}); +result1.booleanFlag; // boolean +>result1.booleanFlag : boolean +> : ^^^^^^^ +>result1 : TypeFlag<{ booleanFlag: { type: BooleanConstructor; }; booleanFlagDefault: { type: BooleanConstructor; default: boolean; }; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>booleanFlag : boolean +> : ^^^^^^^ + +result1.booleanFlagDefault; // boolean +>result1.booleanFlagDefault : boolean +> : ^^^^^^^ +>result1 : TypeFlag<{ booleanFlag: { type: BooleanConstructor; }; booleanFlagDefault: { type: BooleanConstructor; default: boolean; }; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>booleanFlagDefault : boolean +> : ^^^^^^^ + +declare function fn2( +>fn2 : (options: Readonly) => TypeFlag +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ + + options: Readonly, +>options : Readonly +> : ^^^^^^^^^^^^^^^^^ + +): TypeFlag; + +const result2 = fn2({ +>result2 : TypeFlag<{ booleanFlag: { type: BooleanConstructor; }; booleanFlagDefault: { type: BooleanConstructor; default: boolean; }; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>fn2({ booleanFlag: { type: Boolean }, booleanFlagDefault: { type: Boolean, default: false, },}) : TypeFlag<{ booleanFlag: { type: BooleanConstructor; }; booleanFlagDefault: { type: BooleanConstructor; default: boolean; }; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>fn2 : (options: Readonly) => TypeFlag +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ booleanFlag: { type: Boolean }, booleanFlagDefault: { type: Boolean, default: false, },} : { booleanFlag: { type: BooleanConstructor; }; booleanFlagDefault: { type: BooleanConstructor; default: false; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + booleanFlag: { type: Boolean }, +>booleanFlag : { type: BooleanConstructor; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ type: Boolean } : { type: BooleanConstructor; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : BooleanConstructor +> : ^^^^^^^^^^^^^^^^^^ +>Boolean : BooleanConstructor +> : ^^^^^^^^^^^^^^^^^^ + + booleanFlagDefault: { +>booleanFlagDefault : { type: BooleanConstructor; default: false; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ type: Boolean, default: false, } : { type: BooleanConstructor; default: false; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + type: Boolean, +>type : BooleanConstructor +> : ^^^^^^^^^^^^^^^^^^ +>Boolean : BooleanConstructor +> : ^^^^^^^^^^^^^^^^^^ + + default: false, +>default : false +> : ^^^^^ +>false : false +> : ^^^^^ + + }, +}); +result2.booleanFlag; // boolean +>result2.booleanFlag : boolean +> : ^^^^^^^ +>result2 : TypeFlag<{ booleanFlag: { type: BooleanConstructor; }; booleanFlagDefault: { type: BooleanConstructor; default: boolean; }; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>booleanFlag : boolean +> : ^^^^^^^ + +result2.booleanFlagDefault; // boolean +>result2.booleanFlagDefault : boolean +> : ^^^^^^^ +>result2 : TypeFlag<{ booleanFlag: { type: BooleanConstructor; }; booleanFlagDefault: { type: BooleanConstructor; default: boolean; }; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>booleanFlagDefault : boolean +> : ^^^^^^^ + +declare function fn3( +>fn3 : (options: Readonly) => Options +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ + + options: Readonly, +>options : Readonly +> : ^^^^^^^^^^^^^^^^^ + +): Options; + +const result3 = fn3({ +>result3 : { booleanFlag: { type: BooleanConstructor; }; booleanFlagDefault: { type: BooleanConstructor; default: boolean; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>fn3({ booleanFlag: { type: Boolean }, booleanFlagDefault: { type: Boolean, default: false, // no cursed EPC failure here },}) : { booleanFlag: { type: BooleanConstructor; }; booleanFlagDefault: { type: BooleanConstructor; default: boolean; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>fn3 : (options: Readonly) => Options +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ booleanFlag: { type: Boolean }, booleanFlagDefault: { type: Boolean, default: false, // no cursed EPC failure here },} : { booleanFlag: { type: BooleanConstructor; }; booleanFlagDefault: { type: BooleanConstructor; default: false; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + booleanFlag: { type: Boolean }, +>booleanFlag : { type: BooleanConstructor; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ type: Boolean } : { type: BooleanConstructor; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : BooleanConstructor +> : ^^^^^^^^^^^^^^^^^^ +>Boolean : BooleanConstructor +> : ^^^^^^^^^^^^^^^^^^ + + booleanFlagDefault: { +>booleanFlagDefault : { type: BooleanConstructor; default: false; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ type: Boolean, default: false, // no cursed EPC failure here } : { type: BooleanConstructor; default: false; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + type: Boolean, +>type : BooleanConstructor +> : ^^^^^^^^^^^^^^^^^^ +>Boolean : BooleanConstructor +> : ^^^^^^^^^^^^^^^^^^ + + default: false, // no cursed EPC failure here +>default : false +> : ^^^^^ +>false : false +> : ^^^^^ + + }, +}); + +declare function takeType(arg: { type: unknown }): void; +>takeType : (arg: { type: unknown; }) => void +> : ^ ^^ ^^^^^ +>arg : { type: unknown; } +> : ^^^^^^^^ ^^^ +>type : unknown +> : ^^^^^^^ + +takeType(result3.booleanFlagDefault); +>takeType(result3.booleanFlagDefault) : void +> : ^^^^ +>takeType : (arg: { type: unknown; }) => void +> : ^ ^^ ^^^^^ +>result3.booleanFlagDefault : { type: BooleanConstructor; default: boolean; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>result3 : { booleanFlag: { type: BooleanConstructor; }; booleanFlagDefault: { type: BooleanConstructor; default: boolean; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>booleanFlagDefault : { type: BooleanConstructor; default: boolean; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/baselines/reference/reverseMappedTypeInferenceWidening2.symbols b/tests/baselines/reference/reverseMappedTypeInferenceWidening2.symbols new file mode 100644 index 0000000000000..a8a620769f1e2 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeInferenceWidening2.symbols @@ -0,0 +1,45 @@ +//// [tests/cases/compiler/reverseMappedTypeInferenceWidening2.ts] //// + +=== reverseMappedTypeInferenceWidening2.ts === +declare function test1>(arg: { +>test1 : Symbol(test1, Decl(reverseMappedTypeInferenceWidening2.ts, 0, 0)) +>T : Symbol(T, Decl(reverseMappedTypeInferenceWidening2.ts, 0, 23)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>prop : Symbol(prop, Decl(reverseMappedTypeInferenceWidening2.ts, 0, 49)) +>arg : Symbol(arg, Decl(reverseMappedTypeInferenceWidening2.ts, 0, 68)) + + [K in keyof T]: T[K]; +>K : Symbol(K, Decl(reverseMappedTypeInferenceWidening2.ts, 1, 3)) +>T : Symbol(T, Decl(reverseMappedTypeInferenceWidening2.ts, 0, 23)) +>T : Symbol(T, Decl(reverseMappedTypeInferenceWidening2.ts, 0, 23)) +>K : Symbol(K, Decl(reverseMappedTypeInferenceWidening2.ts, 1, 3)) + +}): T; +>T : Symbol(T, Decl(reverseMappedTypeInferenceWidening2.ts, 0, 23)) + +const res1 = test1({ +>res1 : Symbol(res1, Decl(reverseMappedTypeInferenceWidening2.ts, 4, 5)) +>test1 : Symbol(test1, Decl(reverseMappedTypeInferenceWidening2.ts, 0, 0)) + + foo: { +>foo : Symbol(foo, Decl(reverseMappedTypeInferenceWidening2.ts, 4, 20)) + + prop: 1, +>prop : Symbol(prop, Decl(reverseMappedTypeInferenceWidening2.ts, 5, 8)) + + prop2: "", +>prop2 : Symbol(prop2, Decl(reverseMappedTypeInferenceWidening2.ts, 6, 12)) + + }, + bar: { +>bar : Symbol(bar, Decl(reverseMappedTypeInferenceWidening2.ts, 8, 4)) + + prop: true, +>prop : Symbol(prop, Decl(reverseMappedTypeInferenceWidening2.ts, 9, 8)) + + prop2: null, +>prop2 : Symbol(prop2, Decl(reverseMappedTypeInferenceWidening2.ts, 10, 15)) + + }, +}); + diff --git a/tests/baselines/reference/reverseMappedTypeInferenceWidening2.types b/tests/baselines/reference/reverseMappedTypeInferenceWidening2.types new file mode 100644 index 0000000000000..347e19be45f4f --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeInferenceWidening2.types @@ -0,0 +1,62 @@ +//// [tests/cases/compiler/reverseMappedTypeInferenceWidening2.ts] //// + +=== reverseMappedTypeInferenceWidening2.ts === +declare function test1>(arg: { +>test1 : >(arg: { [K in keyof T]: T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>prop : unknown +> : ^^^^^^^ +>arg : { [K in keyof T]: T[K]; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^ + + [K in keyof T]: T[K]; +}): T; + +const res1 = test1({ +>res1 : { foo: { prop: number; prop2: string; }; bar: { prop: boolean; prop2: null; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>test1({ foo: { prop: 1, prop2: "", }, bar: { prop: true, prop2: null, },}) : { foo: { prop: number; prop2: string; }; bar: { prop: boolean; prop2: null; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>test1 : >(arg: { [K in keyof T]: T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ foo: { prop: 1, prop2: "", }, bar: { prop: true, prop2: null, },} : { foo: { prop: number; prop2: string; }; bar: { prop: true; prop2: null; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + foo: { +>foo : { prop: number; prop2: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ prop: 1, prop2: "", } : { prop: number; prop2: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + prop: 1, +>prop : number +> : ^^^^^^ +>1 : 1 +> : ^ + + prop2: "", +>prop2 : string +> : ^^^^^^ +>"" : "" +> : ^^ + + }, + bar: { +>bar : { prop: true; prop2: null; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ prop: true, prop2: null, } : { prop: true; prop2: null; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + prop: true, +>prop : true +> : ^^^^ +>true : true +> : ^^^^ + + prop2: null, +>prop2 : null +> : ^^^^ + + }, +}); + diff --git a/tests/cases/compiler/reverseMappedTypeInferenceWidening1.ts b/tests/cases/compiler/reverseMappedTypeInferenceWidening1.ts new file mode 100644 index 0000000000000..bbaae1d00e01e --- /dev/null +++ b/tests/cases/compiler/reverseMappedTypeInferenceWidening1.ts @@ -0,0 +1,60 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/62720 + +type TypeFunction = (...args: any[]) => ReturnType; +type Flags = { + [flagName: string]: { + type: TypeFunction; + default?: unknown; + }; +}; +type TypeFlag = { + [flag in keyof Schemas]: Schemas[flag] extends { type: TypeFunction } + ? T + : never; +}; + +declare function fn1( + options: Options, +): TypeFlag; + +const result1 = fn1({ + booleanFlag: { type: Boolean }, + booleanFlagDefault: { + type: Boolean, + default: false, + }, +}); +result1.booleanFlag; // boolean +result1.booleanFlagDefault; // boolean + +declare function fn2( + options: Readonly, +): TypeFlag; + +const result2 = fn2({ + booleanFlag: { type: Boolean }, + booleanFlagDefault: { + type: Boolean, + default: false, + }, +}); +result2.booleanFlag; // boolean +result2.booleanFlagDefault; // boolean + +declare function fn3( + options: Readonly, +): Options; + +const result3 = fn3({ + booleanFlag: { type: Boolean }, + booleanFlagDefault: { + type: Boolean, + default: false, // no cursed EPC failure here + }, +}); + +declare function takeType(arg: { type: unknown }): void; +takeType(result3.booleanFlagDefault); diff --git a/tests/cases/compiler/reverseMappedTypeInferenceWidening2.ts b/tests/cases/compiler/reverseMappedTypeInferenceWidening2.ts new file mode 100644 index 0000000000000..56502f73d4f70 --- /dev/null +++ b/tests/cases/compiler/reverseMappedTypeInferenceWidening2.ts @@ -0,0 +1,17 @@ +// @strict: true +// @noEmit: true + +declare function test1>(arg: { + [K in keyof T]: T[K]; +}): T; + +const res1 = test1({ + foo: { + prop: 1, + prop2: "", + }, + bar: { + prop: true, + prop2: null, + }, +});