From d9c56f2f8f1937ad85f65b26f196ef0a41bb887e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sun, 16 Jul 2023 00:58:00 +0200 Subject: [PATCH 1/2] Fixed inferred const rest types in signatures --- src/compiler/checker.ts | 6 +- .../typeParameterConstModifiers.errors.txt | 25 +++++- .../reference/typeParameterConstModifiers.js | 41 +++++++++- .../typeParameterConstModifiers.symbols | 65 ++++++++++++++++ .../typeParameterConstModifiers.types | 76 +++++++++++++++++++ 5 files changed, 208 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 73a15fd578777..23dd5366d1694 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -23925,7 +23925,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { callback(getTypeAtPosition(source, i), getTypeAtPosition(target, i)); } if (targetRestType) { - callback(getRestTypeAtPosition(source, paramCount), targetRestType); + callback(getRestTypeAtPosition(source, paramCount, /*readonly*/ isConstTypeVariable(targetRestType)), targetRestType); } } @@ -34928,7 +34928,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; } - function getRestTypeAtPosition(source: Signature, pos: number): Type { + function getRestTypeAtPosition(source: Signature, pos: number, readonly?: boolean): Type { const parameterCount = getParameterCount(source); const minArgumentCount = getMinArgumentCount(source); const restType = getEffectiveRestType(source); @@ -34952,7 +34952,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { names.push(name); } } - return createTupleType(types, flags, /*readonly*/ false, length(names) === length(types) ? names : undefined); + return createTupleType(types, flags, readonly, length(names) === length(types) ? names : undefined); } // Return the number of parameters in a signature. The rest parameter, if present, counts as one diff --git a/tests/baselines/reference/typeParameterConstModifiers.errors.txt b/tests/baselines/reference/typeParameterConstModifiers.errors.txt index 8a57e4b939313..872f0fe8910a2 100644 --- a/tests/baselines/reference/typeParameterConstModifiers.errors.txt +++ b/tests/baselines/reference/typeParameterConstModifiers.errors.txt @@ -107,4 +107,27 @@ typeParameterConstModifiers.ts(55,9): error TS1277: 'const' modifier can only ap const thingMapped = >(o: NotEmptyMapped) => o; const tMapped = thingMapped({ foo: '' }); // { foo: "" } - \ No newline at end of file + + // repro from https://github.com/microsoft/TypeScript/issues/55033 + + function factory_55033_minimal(cb: (...args: T) => void) { + return {} as T + } + + const test_55033_minimal = factory_55033_minimal((b: string) => {}) + + function factory_55033(cb: (...args: T) => void) { + return function call(...args: K): K { + return {} as K; + }; + } + + const t1_55033 = factory_55033((a: { test: number }, b: string) => {})( + { test: 123 }, + "some string" + ); + + const t2_55033 = factory_55033((a: { test: number }, b: string) => {})( + { test: 123 } as const, + "some string" + ); \ No newline at end of file diff --git a/tests/baselines/reference/typeParameterConstModifiers.js b/tests/baselines/reference/typeParameterConstModifiers.js index 3fe57ad97a0e4..b52cded2b902d 100644 --- a/tests/baselines/reference/typeParameterConstModifiers.js +++ b/tests/baselines/reference/typeParameterConstModifiers.js @@ -101,7 +101,30 @@ type NotEmptyMapped> = keyof T extends never ? nev const thingMapped = >(o: NotEmptyMapped) => o; const tMapped = thingMapped({ foo: '' }); // { foo: "" } - + +// repro from https://github.com/microsoft/TypeScript/issues/55033 + +function factory_55033_minimal(cb: (...args: T) => void) { + return {} as T +} + +const test_55033_minimal = factory_55033_minimal((b: string) => {}) + +function factory_55033(cb: (...args: T) => void) { + return function call(...args: K): K { + return {} as K; + }; +} + +const t1_55033 = factory_55033((a: { test: number }, b: string) => {})( + { test: 123 }, + "some string" +); + +const t2_55033 = factory_55033((a: { test: number }, b: string) => {})( + { test: 123 } as const, + "some string" +); //// [typeParameterConstModifiers.js] "use strict"; @@ -154,3 +177,19 @@ var thing = function (o) { return o; }; var t = thing({ foo: '' }); // readonly { foo: "" } var thingMapped = function (o) { return o; }; var tMapped = thingMapped({ foo: '' }); // { foo: "" } +// repro from https://github.com/microsoft/TypeScript/issues/55033 +function factory_55033_minimal(cb) { + return {}; +} +var test_55033_minimal = factory_55033_minimal(function (b) { }); +function factory_55033(cb) { + return function call() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + return {}; + }; +} +var t1_55033 = factory_55033(function (a, b) { })({ test: 123 }, "some string"); +var t2_55033 = factory_55033(function (a, b) { })({ test: 123 }, "some string"); diff --git a/tests/baselines/reference/typeParameterConstModifiers.symbols b/tests/baselines/reference/typeParameterConstModifiers.symbols index 2ec51bed100f0..371a38201488f 100644 --- a/tests/baselines/reference/typeParameterConstModifiers.symbols +++ b/tests/baselines/reference/typeParameterConstModifiers.symbols @@ -361,3 +361,68 @@ const tMapped = thingMapped({ foo: '' }); // { foo: "" } >thingMapped : Symbol(thingMapped, Decl(typeParameterConstModifiers.ts, 97, 5)) >foo : Symbol(foo, Decl(typeParameterConstModifiers.ts, 99, 29)) +// repro from https://github.com/microsoft/TypeScript/issues/55033 + +function factory_55033_minimal(cb: (...args: T) => void) { +>factory_55033_minimal : Symbol(factory_55033_minimal, Decl(typeParameterConstModifiers.ts, 99, 41)) +>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 103, 31)) +>cb : Symbol(cb, Decl(typeParameterConstModifiers.ts, 103, 67)) +>args : Symbol(args, Decl(typeParameterConstModifiers.ts, 103, 72)) +>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 103, 31)) + + return {} as T +>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 103, 31)) +} + +const test_55033_minimal = factory_55033_minimal((b: string) => {}) +>test_55033_minimal : Symbol(test_55033_minimal, Decl(typeParameterConstModifiers.ts, 107, 5)) +>factory_55033_minimal : Symbol(factory_55033_minimal, Decl(typeParameterConstModifiers.ts, 99, 41)) +>b : Symbol(b, Decl(typeParameterConstModifiers.ts, 107, 50)) + +function factory_55033(cb: (...args: T) => void) { +>factory_55033 : Symbol(factory_55033, Decl(typeParameterConstModifiers.ts, 107, 67)) +>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 109, 23)) +>cb : Symbol(cb, Decl(typeParameterConstModifiers.ts, 109, 59)) +>args : Symbol(args, Decl(typeParameterConstModifiers.ts, 109, 64)) +>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 109, 23)) + + return function call(...args: K): K { +>call : Symbol(call, Decl(typeParameterConstModifiers.ts, 110, 10)) +>K : Symbol(K, Decl(typeParameterConstModifiers.ts, 110, 25)) +>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 109, 23)) +>args : Symbol(args, Decl(typeParameterConstModifiers.ts, 110, 44)) +>K : Symbol(K, Decl(typeParameterConstModifiers.ts, 110, 25)) +>K : Symbol(K, Decl(typeParameterConstModifiers.ts, 110, 25)) + + return {} as K; +>K : Symbol(K, Decl(typeParameterConstModifiers.ts, 110, 25)) + + }; +} + +const t1_55033 = factory_55033((a: { test: number }, b: string) => {})( +>t1_55033 : Symbol(t1_55033, Decl(typeParameterConstModifiers.ts, 115, 5)) +>factory_55033 : Symbol(factory_55033, Decl(typeParameterConstModifiers.ts, 107, 67)) +>a : Symbol(a, Decl(typeParameterConstModifiers.ts, 115, 32)) +>test : Symbol(test, Decl(typeParameterConstModifiers.ts, 115, 36)) +>b : Symbol(b, Decl(typeParameterConstModifiers.ts, 115, 52)) + + { test: 123 }, +>test : Symbol(test, Decl(typeParameterConstModifiers.ts, 116, 5)) + + "some string" +); + +const t2_55033 = factory_55033((a: { test: number }, b: string) => {})( +>t2_55033 : Symbol(t2_55033, Decl(typeParameterConstModifiers.ts, 120, 5)) +>factory_55033 : Symbol(factory_55033, Decl(typeParameterConstModifiers.ts, 107, 67)) +>a : Symbol(a, Decl(typeParameterConstModifiers.ts, 120, 32)) +>test : Symbol(test, Decl(typeParameterConstModifiers.ts, 120, 36)) +>b : Symbol(b, Decl(typeParameterConstModifiers.ts, 120, 52)) + + { test: 123 } as const, +>test : Symbol(test, Decl(typeParameterConstModifiers.ts, 121, 5)) +>const : Symbol(const) + + "some string" +); diff --git a/tests/baselines/reference/typeParameterConstModifiers.types b/tests/baselines/reference/typeParameterConstModifiers.types index 809a64ce0b70c..6c87617c96c9a 100644 --- a/tests/baselines/reference/typeParameterConstModifiers.types +++ b/tests/baselines/reference/typeParameterConstModifiers.types @@ -409,3 +409,79 @@ const tMapped = thingMapped({ foo: '' }); // { foo: "" } >foo : "" >'' : "" +// repro from https://github.com/microsoft/TypeScript/issues/55033 + +function factory_55033_minimal(cb: (...args: T) => void) { +>factory_55033_minimal : (cb: (...args: T) => void) => T +>cb : (...args: T) => void +>args : T + + return {} as T +>{} as T : T +>{} : {} +} + +const test_55033_minimal = factory_55033_minimal((b: string) => {}) +>test_55033_minimal : readonly [b: string] +>factory_55033_minimal((b: string) => {}) : readonly [b: string] +>factory_55033_minimal : (cb: (...args: T) => void) => T +>(b: string) => {} : (b: string) => void +>b : string + +function factory_55033(cb: (...args: T) => void) { +>factory_55033 : (cb: (...args: T) => void) => (...args: K) => K +>cb : (...args: T) => void +>args : T + + return function call(...args: K): K { +>function call(...args: K): K { return {} as K; } : (...args: K) => K +>call : (...args: K) => K +>args : K + + return {} as K; +>{} as K : K +>{} : {} + + }; +} + +const t1_55033 = factory_55033((a: { test: number }, b: string) => {})( +>t1_55033 : readonly [{ readonly test: 123; }, "some string"] +>factory_55033((a: { test: number }, b: string) => {})( { test: 123 }, "some string") : readonly [{ readonly test: 123; }, "some string"] +>factory_55033((a: { test: number }, b: string) => {}) : (...args: K) => K +>factory_55033 : (cb: (...args: T) => void) => (...args: K) => K +>(a: { test: number }, b: string) => {} : (a: { test: number;}, b: string) => void +>a : { test: number; } +>test : number +>b : string + + { test: 123 }, +>{ test: 123 } : { test: 123; } +>test : 123 +>123 : 123 + + "some string" +>"some string" : "some string" + +); + +const t2_55033 = factory_55033((a: { test: number }, b: string) => {})( +>t2_55033 : readonly [{ readonly test: 123; }, "some string"] +>factory_55033((a: { test: number }, b: string) => {})( { test: 123 } as const, "some string") : readonly [{ readonly test: 123; }, "some string"] +>factory_55033((a: { test: number }, b: string) => {}) : (...args: K) => K +>factory_55033 : (cb: (...args: T) => void) => (...args: K) => K +>(a: { test: number }, b: string) => {} : (a: { test: number;}, b: string) => void +>a : { test: number; } +>test : number +>b : string + + { test: 123 } as const, +>{ test: 123 } as const : { readonly test: 123; } +>{ test: 123 } : { readonly test: 123; } +>test : 123 +>123 : 123 + + "some string" +>"some string" : "some string" + +); From fb32b835e3b70399d2cb2c261f782739c41d672a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sun, 16 Jul 2023 08:45:11 +0200 Subject: [PATCH 2/2] Add missing test change --- .../typeParameterConstModifiers.ts | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/cases/conformance/types/typeParameters/typeParameterLists/typeParameterConstModifiers.ts b/tests/cases/conformance/types/typeParameters/typeParameterLists/typeParameterConstModifiers.ts index b66b92ff7024b..448f007da972d 100644 --- a/tests/cases/conformance/types/typeParameters/typeParameterLists/typeParameterConstModifiers.ts +++ b/tests/cases/conformance/types/typeParameters/typeParameterLists/typeParameterConstModifiers.ts @@ -100,3 +100,27 @@ type NotEmptyMapped> = keyof T extends never ? nev const thingMapped = >(o: NotEmptyMapped) => o; const tMapped = thingMapped({ foo: '' }); // { foo: "" } + +// repro from https://github.com/microsoft/TypeScript/issues/55033 + +function factory_55033_minimal(cb: (...args: T) => void) { + return {} as T +} + +const test_55033_minimal = factory_55033_minimal((b: string) => {}) + +function factory_55033(cb: (...args: T) => void) { + return function call(...args: K): K { + return {} as K; + }; +} + +const t1_55033 = factory_55033((a: { test: number }, b: string) => {})( + { test: 123 }, + "some string" +); + +const t2_55033 = factory_55033((a: { test: number }, b: string) => {})( + { test: 123 } as const, + "some string" +); \ No newline at end of file