mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-12-10 00:20:22 -06:00
Widen reverse mapped type properties to fix them being treated as EPC-valid sources (#62722)
This commit is contained in:
parent
b33d37201e
commit
0752278137
@ -26438,7 +26438,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 {
|
||||
|
||||
@ -0,0 +1,181 @@
|
||||
//// [tests/cases/compiler/reverseMappedTypeInferenceWidening1.ts] ////
|
||||
|
||||
=== reverseMappedTypeInferenceWidening1.ts ===
|
||||
// https://github.com/microsoft/TypeScript/issues/62720
|
||||
|
||||
type TypeFunction<ReturnType = unknown> = (...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<Schemas extends Flags> = {
|
||||
>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<infer T> }
|
||||
>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<Options extends Flags>(
|
||||
>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<Options>;
|
||||
>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<Options extends Flags>(
|
||||
>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>,
|
||||
>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<Options>;
|
||||
>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<Options extends Flags>(
|
||||
>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>,
|
||||
>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))
|
||||
|
||||
@ -0,0 +1,244 @@
|
||||
//// [tests/cases/compiler/reverseMappedTypeInferenceWidening1.ts] ////
|
||||
|
||||
=== reverseMappedTypeInferenceWidening1.ts ===
|
||||
// https://github.com/microsoft/TypeScript/issues/62720
|
||||
|
||||
type TypeFunction<ReturnType = unknown> = (...args: any[]) => ReturnType;
|
||||
>TypeFunction : TypeFunction<ReturnType>
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>args : any[]
|
||||
> : ^^^^^
|
||||
|
||||
type Flags = {
|
||||
>Flags : Flags
|
||||
> : ^^^^^
|
||||
|
||||
[flagName: string]: {
|
||||
>flagName : string
|
||||
> : ^^^^^^
|
||||
|
||||
type: TypeFunction;
|
||||
>type : TypeFunction<unknown>
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
default?: unknown;
|
||||
>default : unknown
|
||||
> : ^^^^^^^
|
||||
|
||||
};
|
||||
};
|
||||
type TypeFlag<Schemas extends Flags> = {
|
||||
>TypeFlag : TypeFlag<Schemas>
|
||||
> : ^^^^^^^^^^^^^^^^^
|
||||
|
||||
[flag in keyof Schemas]: Schemas[flag] extends { type: TypeFunction<infer T> }
|
||||
>type : TypeFunction<T>
|
||||
> : ^^^^^^^^^^^^^^^
|
||||
|
||||
? T
|
||||
: never;
|
||||
};
|
||||
|
||||
declare function fn1<Options extends Flags>(
|
||||
>fn1 : <Options extends Flags>(options: Options) => TypeFlag<Options>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
|
||||
options: Options,
|
||||
>options : Options
|
||||
> : ^^^^^^^
|
||||
|
||||
): TypeFlag<Options>;
|
||||
|
||||
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 extends Flags>(options: Options) => TypeFlag<Options>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>{ 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<Options extends Flags>(
|
||||
>fn2 : <Options extends Flags>(options: Readonly<Options>) => TypeFlag<Options>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
|
||||
options: Readonly<Options>,
|
||||
>options : Readonly<Options>
|
||||
> : ^^^^^^^^^^^^^^^^^
|
||||
|
||||
): TypeFlag<Options>;
|
||||
|
||||
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 extends Flags>(options: Readonly<Options>) => TypeFlag<Options>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>{ 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<Options extends Flags>(
|
||||
>fn3 : <Options extends Flags>(options: Readonly<Options>) => Options
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
|
||||
options: Readonly<Options>,
|
||||
>options : Readonly<Options>
|
||||
> : ^^^^^^^^^^^^^^^^^
|
||||
|
||||
): 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 extends Flags>(options: Readonly<Options>) => 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; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
//// [tests/cases/compiler/reverseMappedTypeInferenceWidening2.ts] ////
|
||||
|
||||
=== reverseMappedTypeInferenceWidening2.ts ===
|
||||
declare function test1<T extends Record<string, { prop: unknown }>>(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))
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
//// [tests/cases/compiler/reverseMappedTypeInferenceWidening2.ts] ////
|
||||
|
||||
=== reverseMappedTypeInferenceWidening2.ts ===
|
||||
declare function test1<T extends Record<string, { prop: unknown }>>(arg: {
|
||||
>test1 : <T extends Record<string, { prop: unknown; }>>(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 : <T extends Record<string, { prop: unknown; }>>(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
|
||||
> : ^^^^
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
60
tests/cases/compiler/reverseMappedTypeInferenceWidening1.ts
Normal file
60
tests/cases/compiler/reverseMappedTypeInferenceWidening1.ts
Normal file
@ -0,0 +1,60 @@
|
||||
// @strict: true
|
||||
// @noEmit: true
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/62720
|
||||
|
||||
type TypeFunction<ReturnType = unknown> = (...args: any[]) => ReturnType;
|
||||
type Flags = {
|
||||
[flagName: string]: {
|
||||
type: TypeFunction;
|
||||
default?: unknown;
|
||||
};
|
||||
};
|
||||
type TypeFlag<Schemas extends Flags> = {
|
||||
[flag in keyof Schemas]: Schemas[flag] extends { type: TypeFunction<infer T> }
|
||||
? T
|
||||
: never;
|
||||
};
|
||||
|
||||
declare function fn1<Options extends Flags>(
|
||||
options: Options,
|
||||
): TypeFlag<Options>;
|
||||
|
||||
const result1 = fn1({
|
||||
booleanFlag: { type: Boolean },
|
||||
booleanFlagDefault: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
result1.booleanFlag; // boolean
|
||||
result1.booleanFlagDefault; // boolean
|
||||
|
||||
declare function fn2<Options extends Flags>(
|
||||
options: Readonly<Options>,
|
||||
): TypeFlag<Options>;
|
||||
|
||||
const result2 = fn2({
|
||||
booleanFlag: { type: Boolean },
|
||||
booleanFlagDefault: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
result2.booleanFlag; // boolean
|
||||
result2.booleanFlagDefault; // boolean
|
||||
|
||||
declare function fn3<Options extends Flags>(
|
||||
options: Readonly<Options>,
|
||||
): 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);
|
||||
17
tests/cases/compiler/reverseMappedTypeInferenceWidening2.ts
Normal file
17
tests/cases/compiler/reverseMappedTypeInferenceWidening2.ts
Normal file
@ -0,0 +1,17 @@
|
||||
// @strict: true
|
||||
// @noEmit: true
|
||||
|
||||
declare function test1<T extends Record<string, { prop: unknown }>>(arg: {
|
||||
[K in keyof T]: T[K];
|
||||
}): T;
|
||||
|
||||
const res1 = test1({
|
||||
foo: {
|
||||
prop: 1,
|
||||
prop2: "",
|
||||
},
|
||||
bar: {
|
||||
prop: true,
|
||||
prop2: null,
|
||||
},
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user