Skip to content

Fixed inferred const rest types in signatures #55034

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down
25 changes: 24 additions & 1 deletion tests/baselines/reference/typeParameterConstModifiers.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,27 @@ typeParameterConstModifiers.ts(55,9): error TS1277: 'const' modifier can only ap
const thingMapped = <const O extends Record<string, any>>(o: NotEmptyMapped<O>) => o;

const tMapped = thingMapped({ foo: '' }); // { foo: "" }


// repro from https://github.com/microsoft/TypeScript/issues/55033

function factory_55033_minimal<const T extends readonly unknown[]>(cb: (...args: T) => void) {
return {} as T
}

const test_55033_minimal = factory_55033_minimal((b: string) => {})

function factory_55033<const T extends readonly unknown[]>(cb: (...args: T) => void) {
return function call<const K extends T>(...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"
);
41 changes: 40 additions & 1 deletion tests/baselines/reference/typeParameterConstModifiers.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,30 @@ type NotEmptyMapped<T extends Record<string, any>> = keyof T extends never ? nev
const thingMapped = <const O extends Record<string, any>>(o: NotEmptyMapped<O>) => o;

const tMapped = thingMapped({ foo: '' }); // { foo: "" }


// repro from https://github.com/microsoft/TypeScript/issues/55033

function factory_55033_minimal<const T extends readonly unknown[]>(cb: (...args: T) => void) {
return {} as T
}

const test_55033_minimal = factory_55033_minimal((b: string) => {})

function factory_55033<const T extends readonly unknown[]>(cb: (...args: T) => void) {
return function call<const K extends T>(...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";
Expand Down Expand Up @@ -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");
65 changes: 65 additions & 0 deletions tests/baselines/reference/typeParameterConstModifiers.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -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<const T extends readonly unknown[]>(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<const T extends readonly unknown[]>(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<const K extends T>(...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"
);
76 changes: 76 additions & 0 deletions tests/baselines/reference/typeParameterConstModifiers.types
Original file line number Diff line number Diff line change
Expand Up @@ -409,3 +409,79 @@ const tMapped = thingMapped({ foo: '' }); // { foo: "" }
>foo : ""
>'' : ""

// repro from https://github.com/microsoft/TypeScript/issues/55033

function factory_55033_minimal<const T extends readonly unknown[]>(cb: (...args: T) => void) {
>factory_55033_minimal : <const T extends readonly unknown[]>(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 : <const T extends readonly unknown[]>(cb: (...args: T) => void) => T
>(b: string) => {} : (b: string) => void
>b : string

function factory_55033<const T extends readonly unknown[]>(cb: (...args: T) => void) {
>factory_55033 : <const T extends readonly unknown[]>(cb: (...args: T) => void) => <const K extends T>(...args: K) => K
>cb : (...args: T) => void
>args : T

return function call<const K extends T>(...args: K): K {
>function call<const K extends T>(...args: K): K { return {} as K; } : <const K extends T>(...args: K) => K
>call : <const K extends T>(...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) => {}) : <const K extends readonly [a: { test: number; }, b: string]>(...args: K) => K
>factory_55033 : <const T extends readonly unknown[]>(cb: (...args: T) => void) => <const K extends T>(...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) => {}) : <const K extends readonly [a: { test: number; }, b: string]>(...args: K) => K
>factory_55033 : <const T extends readonly unknown[]>(cb: (...args: T) => void) => <const K extends T>(...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"

);
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,27 @@ type NotEmptyMapped<T extends Record<string, any>> = keyof T extends never ? nev
const thingMapped = <const O extends Record<string, any>>(o: NotEmptyMapped<O>) => o;

const tMapped = thingMapped({ foo: '' }); // { foo: "" }

// repro from https://github.com/microsoft/TypeScript/issues/55033

function factory_55033_minimal<const T extends readonly unknown[]>(cb: (...args: T) => void) {
return {} as T
}

const test_55033_minimal = factory_55033_minimal((b: string) => {})

function factory_55033<const T extends readonly unknown[]>(cb: (...args: T) => void) {
return function call<const K extends T>(...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"
);