diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0567712f11da3..dec3d6542422f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18989,6 +18989,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { type.flags & TypeFlags.Intersection ? getUnionType(map((type as IntersectionType).types, t => getIndexType(t, indexFlags))) : getObjectFlags(type) & ObjectFlags.Mapped ? getIndexTypeForMappedType(type as MappedType, indexFlags) : type === wildcardType ? wildcardType : + type === silentNeverType ? silentNeverType : type.flags & TypeFlags.Unknown ? neverType : type.flags & (TypeFlags.Any | TypeFlags.Never) ? stringNumberSymbolType : getLiteralTypeFromProperties(type, (indexFlags & IndexFlags.NoIndexSignatures ? TypeFlags.StringLiteral : TypeFlags.StringLike) | (indexFlags & IndexFlags.StringsOnly ? 0 : TypeFlags.NumberLike | TypeFlags.ESSymbolLike), indexFlags === IndexFlags.None); diff --git a/tests/baselines/reference/silentNeverTypeKeyofLeak.symbols b/tests/baselines/reference/silentNeverTypeKeyofLeak.symbols new file mode 100644 index 0000000000000..5f21c2420b113 --- /dev/null +++ b/tests/baselines/reference/silentNeverTypeKeyofLeak.symbols @@ -0,0 +1,143 @@ +//// [tests/cases/compiler/silentNeverTypeKeyofLeak.ts] //// + +=== silentNeverTypeKeyofLeak.ts === +// Repro from #62824 + +// Minimal repro: silentNeverType leaks through keyof in mapped types +// when a nested generic call has no inference candidates during the +// outer call's inference pass. + +type Fn = (arg: T) => void; +>Fn : Symbol(Fn, Decl(silentNeverTypeKeyofLeak.ts, 0, 0)) +>T : Symbol(T, Decl(silentNeverTypeKeyofLeak.ts, 6, 8)) +>arg : Symbol(arg, Decl(silentNeverTypeKeyofLeak.ts, 6, 14)) +>T : Symbol(T, Decl(silentNeverTypeKeyofLeak.ts, 6, 8)) + +declare function fn1(): Fn; +>fn1 : Symbol(fn1, Decl(silentNeverTypeKeyofLeak.ts, 6, 30)) +>T : Symbol(T, Decl(silentNeverTypeKeyofLeak.ts, 8, 21)) +>Fn : Symbol(Fn, Decl(silentNeverTypeKeyofLeak.ts, 0, 0)) +>T : Symbol(T, Decl(silentNeverTypeKeyofLeak.ts, 8, 21)) + +declare function fn2( +>fn2 : Symbol(fn2, Decl(silentNeverTypeKeyofLeak.ts, 8, 33)) +>T : Symbol(T, Decl(silentNeverTypeKeyofLeak.ts, 10, 21)) + + ac: Fn<{ +>ac : Symbol(ac, Decl(silentNeverTypeKeyofLeak.ts, 10, 24)) +>Fn : Symbol(Fn, Decl(silentNeverTypeKeyofLeak.ts, 0, 0)) + + [K in keyof T & string]: T[K]; +>K : Symbol(K, Decl(silentNeverTypeKeyofLeak.ts, 12, 5)) +>T : Symbol(T, Decl(silentNeverTypeKeyofLeak.ts, 10, 21)) +>T : Symbol(T, Decl(silentNeverTypeKeyofLeak.ts, 10, 21)) +>K : Symbol(K, Decl(silentNeverTypeKeyofLeak.ts, 12, 5)) + + }>, +): void; + +fn2(fn1()); +>fn2 : Symbol(fn2, Decl(silentNeverTypeKeyofLeak.ts, 8, 33)) +>fn1 : Symbol(fn1, Decl(silentNeverTypeKeyofLeak.ts, 6, 30)) + +// Shorter repro from issue +type Values = T[keyof T]; +>Values : Symbol(Values, Decl(silentNeverTypeKeyofLeak.ts, 16, 11)) +>T : Symbol(T, Decl(silentNeverTypeKeyofLeak.ts, 19, 12)) +>T : Symbol(T, Decl(silentNeverTypeKeyofLeak.ts, 19, 12)) +>T : Symbol(T, Decl(silentNeverTypeKeyofLeak.ts, 19, 12)) + +interface ParameterizedObject { +>ParameterizedObject : Symbol(ParameterizedObject, Decl(silentNeverTypeKeyofLeak.ts, 19, 28)) + + type: string; +>type : Symbol(ParameterizedObject.type, Decl(silentNeverTypeKeyofLeak.ts, 21, 31)) + + params?: unknown; +>params : Symbol(ParameterizedObject.params, Decl(silentNeverTypeKeyofLeak.ts, 22, 15)) +} + +type ActionFunction = { +>ActionFunction : Symbol(ActionFunction, Decl(silentNeverTypeKeyofLeak.ts, 24, 1)) +>TParams : Symbol(TParams, Decl(silentNeverTypeKeyofLeak.ts, 26, 20)) +>TAction : Symbol(TAction, Decl(silentNeverTypeKeyofLeak.ts, 26, 28)) +>ParameterizedObject : Symbol(ParameterizedObject, Decl(silentNeverTypeKeyofLeak.ts, 19, 28)) + + (params: TParams): void; +>params : Symbol(params, Decl(silentNeverTypeKeyofLeak.ts, 27, 3)) +>TParams : Symbol(TParams, Decl(silentNeverTypeKeyofLeak.ts, 26, 20)) + + _out_TAction?: TAction; +>_out_TAction : Symbol(_out_TAction, Decl(silentNeverTypeKeyofLeak.ts, 27, 26)) +>TAction : Symbol(TAction, Decl(silentNeverTypeKeyofLeak.ts, 26, 28)) + +}; + +type ToParameterizedObject = Values<{ +>ToParameterizedObject : Symbol(ToParameterizedObject, Decl(silentNeverTypeKeyofLeak.ts, 29, 2)) +>TParameterizedMap : Symbol(TParameterizedMap, Decl(silentNeverTypeKeyofLeak.ts, 31, 27)) +>Values : Symbol(Values, Decl(silentNeverTypeKeyofLeak.ts, 16, 11)) + + [K in keyof TParameterizedMap & string]: { +>K : Symbol(K, Decl(silentNeverTypeKeyofLeak.ts, 32, 3)) +>TParameterizedMap : Symbol(TParameterizedMap, Decl(silentNeverTypeKeyofLeak.ts, 31, 27)) + + type: K; +>type : Symbol(type, Decl(silentNeverTypeKeyofLeak.ts, 32, 44)) +>K : Symbol(K, Decl(silentNeverTypeKeyofLeak.ts, 32, 3)) + + params: TParameterizedMap[K]; +>params : Symbol(params, Decl(silentNeverTypeKeyofLeak.ts, 33, 12)) +>TParameterizedMap : Symbol(TParameterizedMap, Decl(silentNeverTypeKeyofLeak.ts, 31, 27)) +>K : Symbol(K, Decl(silentNeverTypeKeyofLeak.ts, 32, 3)) + + }; +}>; + +declare function enqueueActions( +>enqueueActions : Symbol(enqueueActions, Decl(silentNeverTypeKeyofLeak.ts, 36, 3)) +>TParams : Symbol(TParams, Decl(silentNeverTypeKeyofLeak.ts, 38, 32)) +>TAction : Symbol(TAction, Decl(silentNeverTypeKeyofLeak.ts, 38, 40)) +>ParameterizedObject : Symbol(ParameterizedObject, Decl(silentNeverTypeKeyofLeak.ts, 19, 28)) + + collect: (params: TParams) => void, +>collect : Symbol(collect, Decl(silentNeverTypeKeyofLeak.ts, 38, 78)) +>params : Symbol(params, Decl(silentNeverTypeKeyofLeak.ts, 39, 12)) +>TParams : Symbol(TParams, Decl(silentNeverTypeKeyofLeak.ts, 38, 32)) + +): ActionFunction; +>ActionFunction : Symbol(ActionFunction, Decl(silentNeverTypeKeyofLeak.ts, 24, 1)) +>TParams : Symbol(TParams, Decl(silentNeverTypeKeyofLeak.ts, 38, 32)) +>TAction : Symbol(TAction, Decl(silentNeverTypeKeyofLeak.ts, 38, 40)) + +declare function setup(actions: { +>setup : Symbol(setup, Decl(silentNeverTypeKeyofLeak.ts, 40, 36)) +>TActions : Symbol(TActions, Decl(silentNeverTypeKeyofLeak.ts, 42, 23)) +>actions : Symbol(actions, Decl(silentNeverTypeKeyofLeak.ts, 42, 33)) + + [K in keyof TActions]: ActionFunction< +>K : Symbol(K, Decl(silentNeverTypeKeyofLeak.ts, 43, 3)) +>TActions : Symbol(TActions, Decl(silentNeverTypeKeyofLeak.ts, 42, 23)) +>ActionFunction : Symbol(ActionFunction, Decl(silentNeverTypeKeyofLeak.ts, 24, 1)) + + TActions[K], +>TActions : Symbol(TActions, Decl(silentNeverTypeKeyofLeak.ts, 42, 23)) +>K : Symbol(K, Decl(silentNeverTypeKeyofLeak.ts, 43, 3)) + + ToParameterizedObject +>ToParameterizedObject : Symbol(ToParameterizedObject, Decl(silentNeverTypeKeyofLeak.ts, 29, 2)) +>TActions : Symbol(TActions, Decl(silentNeverTypeKeyofLeak.ts, 42, 23)) + + >; +}): void; + +setup({ +>setup : Symbol(setup, Decl(silentNeverTypeKeyofLeak.ts, 40, 36)) + + doStuff: enqueueActions((params: number) => {}), +>doStuff : Symbol(doStuff, Decl(silentNeverTypeKeyofLeak.ts, 49, 7)) +>enqueueActions : Symbol(enqueueActions, Decl(silentNeverTypeKeyofLeak.ts, 36, 3)) +>params : Symbol(params, Decl(silentNeverTypeKeyofLeak.ts, 50, 27)) + +}); + diff --git a/tests/baselines/reference/silentNeverTypeKeyofLeak.types b/tests/baselines/reference/silentNeverTypeKeyofLeak.types new file mode 100644 index 0000000000000..d952cdc627156 --- /dev/null +++ b/tests/baselines/reference/silentNeverTypeKeyofLeak.types @@ -0,0 +1,132 @@ +//// [tests/cases/compiler/silentNeverTypeKeyofLeak.ts] //// + +=== silentNeverTypeKeyofLeak.ts === +// Repro from #62824 + +// Minimal repro: silentNeverType leaks through keyof in mapped types +// when a nested generic call has no inference candidates during the +// outer call's inference pass. + +type Fn = (arg: T) => void; +>Fn : Fn +> : ^^^^^ +>arg : T +> : ^ + +declare function fn1(): Fn; +>fn1 : () => Fn +> : ^ ^^^^^^^ + +declare function fn2( +>fn2 : (ac: Fn<{ [K in keyof T & string]: T[K]; }>) => void +> : ^ ^^ ^^ ^^^^^ + + ac: Fn<{ +>ac : Fn<{ [K in keyof T & string]: T[K]; }> +> : ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + [K in keyof T & string]: T[K]; + }>, +): void; + +fn2(fn1()); +>fn2(fn1()) : void +> : ^^^^ +>fn2 : (ac: Fn<{ [K in keyof T & string]: T[K]; }>) => void +> : ^ ^^ ^^ ^^^^^ +>fn1() : Fn<{}> +> : ^^^^^^ +>fn1 : () => Fn +> : ^ ^^^^^^^ + +// Shorter repro from issue +type Values = T[keyof T]; +>Values : Values +> : ^^^^^^^^^ + +interface ParameterizedObject { + type: string; +>type : string +> : ^^^^^^ + + params?: unknown; +>params : unknown +> : ^^^^^^^ +} + +type ActionFunction = { +>ActionFunction : ActionFunction +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + (params: TParams): void; +>params : TParams +> : ^^^^^^^ + + _out_TAction?: TAction; +>_out_TAction : TAction | undefined +> : ^^^^^^^^^^^^^^^^^^^ + +}; + +type ToParameterizedObject = Values<{ +>ToParameterizedObject : ToParameterizedObject +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + [K in keyof TParameterizedMap & string]: { + type: K; +>type : K +> : ^ + + params: TParameterizedMap[K]; +>params : TParameterizedMap[K] +> : ^^^^^^^^^^^^^^^^^^^^ + + }; +}>; + +declare function enqueueActions( +>enqueueActions : (collect: (params: TParams) => void) => ActionFunction +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^^^^ + + collect: (params: TParams) => void, +>collect : (params: TParams) => void +> : ^ ^^ ^^^^^ +>params : TParams +> : ^^^^^^^ + +): ActionFunction; + +declare function setup(actions: { +>setup : (actions: { [K in keyof TActions]: ActionFunction>; }) => void +> : ^ ^^ ^^ ^^^^^ +>actions : { [K in keyof TActions]: ActionFunction>; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + [K in keyof TActions]: ActionFunction< + TActions[K], + ToParameterizedObject + >; +}): void; + +setup({ +>setup({ doStuff: enqueueActions((params: number) => {}),}) : void +> : ^^^^ +>setup : (actions: { [K in keyof TActions]: ActionFunction>; }) => void +> : ^ ^^ ^^ ^^^^^ +>{ doStuff: enqueueActions((params: number) => {}),} : { doStuff: ActionFunction; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + doStuff: enqueueActions((params: number) => {}), +>doStuff : ActionFunction +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>enqueueActions((params: number) => {}) : ActionFunction +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>enqueueActions : (collect: (params: TParams) => void) => ActionFunction +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>(params: number) => {} : (params: number) => void +> : ^ ^^ ^^^^^^^^^ +>params : number +> : ^^^^^^ + +}); + diff --git a/tests/cases/compiler/silentNeverTypeKeyofLeak.ts b/tests/cases/compiler/silentNeverTypeKeyofLeak.ts new file mode 100644 index 0000000000000..2d41dcb2db1b1 --- /dev/null +++ b/tests/cases/compiler/silentNeverTypeKeyofLeak.ts @@ -0,0 +1,55 @@ +// @strict: true +// @noEmit: true + +// Repro from #62824 + +// Minimal repro: silentNeverType leaks through keyof in mapped types +// when a nested generic call has no inference candidates during the +// outer call's inference pass. + +type Fn = (arg: T) => void; + +declare function fn1(): Fn; + +declare function fn2( + ac: Fn<{ + [K in keyof T & string]: T[K]; + }>, +): void; + +fn2(fn1()); + +// Shorter repro from issue +type Values = T[keyof T]; + +interface ParameterizedObject { + type: string; + params?: unknown; +} + +type ActionFunction = { + (params: TParams): void; + _out_TAction?: TAction; +}; + +type ToParameterizedObject = Values<{ + [K in keyof TParameterizedMap & string]: { + type: K; + params: TParameterizedMap[K]; + }; +}>; + +declare function enqueueActions( + collect: (params: TParams) => void, +): ActionFunction; + +declare function setup(actions: { + [K in keyof TActions]: ActionFunction< + TActions[K], + ToParameterizedObject + >; +}): void; + +setup({ + doStuff: enqueueActions((params: number) => {}), +});