mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-03-15 14:05:47 -05:00
Only infer readonly tuples for const type parameters when constraints permit (#55229)
Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
This commit is contained in:
@@ -23674,6 +23674,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return isArrayType(type) || !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType);
|
||||
}
|
||||
|
||||
function isMutableArrayLikeType(type: Type): boolean {
|
||||
// A type is mutable-array-like if it is a reference to the global Array type, or if it is not the
|
||||
// any, undefined or null type and if it is assignable to Array<any>
|
||||
return isMutableArrayOrTuple(type) || !(type.flags & (TypeFlags.Any | TypeFlags.Nullable)) && isTypeAssignableTo(type, anyArrayType);
|
||||
}
|
||||
|
||||
function getSingleBaseForNonAugmentingSubtype(type: Type) {
|
||||
if (!(getObjectFlags(type) & ObjectFlags.Reference) || !(getObjectFlags((type as TypeReference).target) & ObjectFlags.ClassOrInterface)) {
|
||||
return undefined;
|
||||
@@ -24338,7 +24344,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) && !someType(targetRestType, isMutableArrayLikeType)), targetRestType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30541,7 +30547,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return createTupleType(elementTypes, elementFlags);
|
||||
}
|
||||
if (forceTuple || inConstContext || inTupleContext) {
|
||||
return createArrayLiteralType(createTupleType(elementTypes, elementFlags, /*readonly*/ inConstContext));
|
||||
return createArrayLiteralType(createTupleType(elementTypes, elementFlags, /*readonly*/ inConstContext && !(contextualType && someType(contextualType, isMutableArrayLikeType))));
|
||||
}
|
||||
return createArrayLiteralType(createArrayType(
|
||||
elementTypes.length ?
|
||||
@@ -33139,7 +33145,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
names.push((arg as SyntheticExpression).tupleNameSource!);
|
||||
}
|
||||
}
|
||||
return createTupleType(types, flags, inConstContext, length(names) === length(types) ? names : undefined);
|
||||
return createTupleType(types, flags, inConstContext && !someType(restType, isMutableArrayLikeType), length(names) === length(types) ? names : undefined);
|
||||
}
|
||||
|
||||
function checkTypeArguments(signature: Signature, typeArgumentNodes: readonly TypeNode[], reportErrors: boolean, headMessage?: DiagnosticMessage): Type[] | undefined {
|
||||
@@ -35455,7 +35461,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);
|
||||
@@ -35479,7 +35485,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
|
||||
|
||||
@@ -107,4 +107,87 @@ 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"
|
||||
);
|
||||
|
||||
// Same with non-readonly constraint
|
||||
|
||||
function factory_55033_2<const T extends unknown[]>(cb: (...args: T) => void) {
|
||||
return function call<const K extends T>(...args: K): K {
|
||||
return {} as K;
|
||||
};
|
||||
}
|
||||
|
||||
const t1_55033_2 = factory_55033_2((a: { test: number }, b: string) => {})(
|
||||
{ test: 123 },
|
||||
"some string"
|
||||
);
|
||||
|
||||
const t2_55033_2 = factory_55033_2((a: { test: number }, b: string) => {})(
|
||||
{ test: 123 } as const,
|
||||
"some string"
|
||||
);
|
||||
|
||||
// Repro from https://github.com/microsoft/TypeScript/issues/51931
|
||||
|
||||
declare function fn<const T extends any[]>(...args: T): T;
|
||||
|
||||
const a = fn("a", false);
|
||||
|
||||
// More examples of non-readonly constraints
|
||||
|
||||
declare function fa1<const T extends unknown[]>(args: T): T;
|
||||
declare function fa2<const T extends readonly unknown[]>(args: T): T;
|
||||
|
||||
fa1(["hello", 42]);
|
||||
fa2(["hello", 42]);
|
||||
|
||||
declare function fb1<const T extends unknown[]>(...args: T): T;
|
||||
declare function fb2<const T extends readonly unknown[]>(...args: T): T;
|
||||
|
||||
fb1("hello", 42);
|
||||
fb2("hello", 42);
|
||||
|
||||
declare function fc1<const T extends unknown[]>(f: (...args: T) => void, ...args: T): T;
|
||||
declare function fc2<const T extends readonly unknown[]>(f: (...args: T) => void, ...args: T): T;
|
||||
|
||||
fc1((a: string, b: number) => {}, "hello", 42);
|
||||
fc2((a: string, b: number) => {}, "hello", 42);
|
||||
|
||||
declare function fd1<const T extends string[] | number[]>(args: T): T;
|
||||
declare function fd2<const T extends string[] | readonly number[]>(args: T): T;
|
||||
declare function fd3<const T extends readonly string[] | readonly number[]>(args: T): T;
|
||||
|
||||
fd1(["hello", "world"]);
|
||||
fd1([1, 2, 3]);
|
||||
fd2(["hello", "world"]);
|
||||
fd2([1, 2, 3]);
|
||||
fd3(["hello", "world"]);
|
||||
fd3([1, 2, 3]);
|
||||
|
||||
declare function fn1<const T extends { foo: unknown[] }[]>(...args: T): T;
|
||||
|
||||
fn1({ foo: ["hello", 123] }, { foo: [true]});
|
||||
|
||||
@@ -101,6 +101,89 @@ 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"
|
||||
);
|
||||
|
||||
// Same with non-readonly constraint
|
||||
|
||||
function factory_55033_2<const T extends unknown[]>(cb: (...args: T) => void) {
|
||||
return function call<const K extends T>(...args: K): K {
|
||||
return {} as K;
|
||||
};
|
||||
}
|
||||
|
||||
const t1_55033_2 = factory_55033_2((a: { test: number }, b: string) => {})(
|
||||
{ test: 123 },
|
||||
"some string"
|
||||
);
|
||||
|
||||
const t2_55033_2 = factory_55033_2((a: { test: number }, b: string) => {})(
|
||||
{ test: 123 } as const,
|
||||
"some string"
|
||||
);
|
||||
|
||||
// Repro from https://github.com/microsoft/TypeScript/issues/51931
|
||||
|
||||
declare function fn<const T extends any[]>(...args: T): T;
|
||||
|
||||
const a = fn("a", false);
|
||||
|
||||
// More examples of non-readonly constraints
|
||||
|
||||
declare function fa1<const T extends unknown[]>(args: T): T;
|
||||
declare function fa2<const T extends readonly unknown[]>(args: T): T;
|
||||
|
||||
fa1(["hello", 42]);
|
||||
fa2(["hello", 42]);
|
||||
|
||||
declare function fb1<const T extends unknown[]>(...args: T): T;
|
||||
declare function fb2<const T extends readonly unknown[]>(...args: T): T;
|
||||
|
||||
fb1("hello", 42);
|
||||
fb2("hello", 42);
|
||||
|
||||
declare function fc1<const T extends unknown[]>(f: (...args: T) => void, ...args: T): T;
|
||||
declare function fc2<const T extends readonly unknown[]>(f: (...args: T) => void, ...args: T): T;
|
||||
|
||||
fc1((a: string, b: number) => {}, "hello", 42);
|
||||
fc2((a: string, b: number) => {}, "hello", 42);
|
||||
|
||||
declare function fd1<const T extends string[] | number[]>(args: T): T;
|
||||
declare function fd2<const T extends string[] | readonly number[]>(args: T): T;
|
||||
declare function fd3<const T extends readonly string[] | readonly number[]>(args: T): T;
|
||||
|
||||
fd1(["hello", "world"]);
|
||||
fd1([1, 2, 3]);
|
||||
fd2(["hello", "world"]);
|
||||
fd2([1, 2, 3]);
|
||||
fd3(["hello", "world"]);
|
||||
fd3([1, 2, 3]);
|
||||
|
||||
declare function fn1<const T extends { foo: unknown[] }[]>(...args: T): T;
|
||||
|
||||
fn1({ foo: ["hello", 123] }, { foo: [true]});
|
||||
|
||||
|
||||
//// [typeParameterConstModifiers.js]
|
||||
@@ -154,3 +237,45 @@ 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");
|
||||
// Same with non-readonly constraint
|
||||
function factory_55033_2(cb) {
|
||||
return function call() {
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
return {};
|
||||
};
|
||||
}
|
||||
var t1_55033_2 = factory_55033_2(function (a, b) { })({ test: 123 }, "some string");
|
||||
var t2_55033_2 = factory_55033_2(function (a, b) { })({ test: 123 }, "some string");
|
||||
var a = fn("a", false);
|
||||
fa1(["hello", 42]);
|
||||
fa2(["hello", 42]);
|
||||
fb1("hello", 42);
|
||||
fb2("hello", 42);
|
||||
fc1(function (a, b) { }, "hello", 42);
|
||||
fc2(function (a, b) { }, "hello", 42);
|
||||
fd1(["hello", "world"]);
|
||||
fd1([1, 2, 3]);
|
||||
fd2(["hello", "world"]);
|
||||
fd2([1, 2, 3]);
|
||||
fd3(["hello", "world"]);
|
||||
fd3([1, 2, 3]);
|
||||
fn1({ foo: ["hello", 123] }, { foo: [true] });
|
||||
|
||||
@@ -361,3 +361,256 @@ 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"
|
||||
);
|
||||
|
||||
// Same with non-readonly constraint
|
||||
|
||||
function factory_55033_2<const T extends unknown[]>(cb: (...args: T) => void) {
|
||||
>factory_55033_2 : Symbol(factory_55033_2, Decl(typeParameterConstModifiers.ts, 123, 2))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 127, 25))
|
||||
>cb : Symbol(cb, Decl(typeParameterConstModifiers.ts, 127, 52))
|
||||
>args : Symbol(args, Decl(typeParameterConstModifiers.ts, 127, 57))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 127, 25))
|
||||
|
||||
return function call<const K extends T>(...args: K): K {
|
||||
>call : Symbol(call, Decl(typeParameterConstModifiers.ts, 128, 10))
|
||||
>K : Symbol(K, Decl(typeParameterConstModifiers.ts, 128, 25))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 127, 25))
|
||||
>args : Symbol(args, Decl(typeParameterConstModifiers.ts, 128, 44))
|
||||
>K : Symbol(K, Decl(typeParameterConstModifiers.ts, 128, 25))
|
||||
>K : Symbol(K, Decl(typeParameterConstModifiers.ts, 128, 25))
|
||||
|
||||
return {} as K;
|
||||
>K : Symbol(K, Decl(typeParameterConstModifiers.ts, 128, 25))
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
const t1_55033_2 = factory_55033_2((a: { test: number }, b: string) => {})(
|
||||
>t1_55033_2 : Symbol(t1_55033_2, Decl(typeParameterConstModifiers.ts, 133, 5))
|
||||
>factory_55033_2 : Symbol(factory_55033_2, Decl(typeParameterConstModifiers.ts, 123, 2))
|
||||
>a : Symbol(a, Decl(typeParameterConstModifiers.ts, 133, 36))
|
||||
>test : Symbol(test, Decl(typeParameterConstModifiers.ts, 133, 40))
|
||||
>b : Symbol(b, Decl(typeParameterConstModifiers.ts, 133, 56))
|
||||
|
||||
{ test: 123 },
|
||||
>test : Symbol(test, Decl(typeParameterConstModifiers.ts, 134, 5))
|
||||
|
||||
"some string"
|
||||
);
|
||||
|
||||
const t2_55033_2 = factory_55033_2((a: { test: number }, b: string) => {})(
|
||||
>t2_55033_2 : Symbol(t2_55033_2, Decl(typeParameterConstModifiers.ts, 138, 5))
|
||||
>factory_55033_2 : Symbol(factory_55033_2, Decl(typeParameterConstModifiers.ts, 123, 2))
|
||||
>a : Symbol(a, Decl(typeParameterConstModifiers.ts, 138, 36))
|
||||
>test : Symbol(test, Decl(typeParameterConstModifiers.ts, 138, 40))
|
||||
>b : Symbol(b, Decl(typeParameterConstModifiers.ts, 138, 56))
|
||||
|
||||
{ test: 123 } as const,
|
||||
>test : Symbol(test, Decl(typeParameterConstModifiers.ts, 139, 5))
|
||||
>const : Symbol(const)
|
||||
|
||||
"some string"
|
||||
);
|
||||
|
||||
// Repro from https://github.com/microsoft/TypeScript/issues/51931
|
||||
|
||||
declare function fn<const T extends any[]>(...args: T): T;
|
||||
>fn : Symbol(fn, Decl(typeParameterConstModifiers.ts, 141, 2))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 145, 20))
|
||||
>args : Symbol(args, Decl(typeParameterConstModifiers.ts, 145, 43))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 145, 20))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 145, 20))
|
||||
|
||||
const a = fn("a", false);
|
||||
>a : Symbol(a, Decl(typeParameterConstModifiers.ts, 147, 5))
|
||||
>fn : Symbol(fn, Decl(typeParameterConstModifiers.ts, 141, 2))
|
||||
|
||||
// More examples of non-readonly constraints
|
||||
|
||||
declare function fa1<const T extends unknown[]>(args: T): T;
|
||||
>fa1 : Symbol(fa1, Decl(typeParameterConstModifiers.ts, 147, 25))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 151, 21))
|
||||
>args : Symbol(args, Decl(typeParameterConstModifiers.ts, 151, 48))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 151, 21))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 151, 21))
|
||||
|
||||
declare function fa2<const T extends readonly unknown[]>(args: T): T;
|
||||
>fa2 : Symbol(fa2, Decl(typeParameterConstModifiers.ts, 151, 60))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 152, 21))
|
||||
>args : Symbol(args, Decl(typeParameterConstModifiers.ts, 152, 57))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 152, 21))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 152, 21))
|
||||
|
||||
fa1(["hello", 42]);
|
||||
>fa1 : Symbol(fa1, Decl(typeParameterConstModifiers.ts, 147, 25))
|
||||
|
||||
fa2(["hello", 42]);
|
||||
>fa2 : Symbol(fa2, Decl(typeParameterConstModifiers.ts, 151, 60))
|
||||
|
||||
declare function fb1<const T extends unknown[]>(...args: T): T;
|
||||
>fb1 : Symbol(fb1, Decl(typeParameterConstModifiers.ts, 155, 19))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 157, 21))
|
||||
>args : Symbol(args, Decl(typeParameterConstModifiers.ts, 157, 48))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 157, 21))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 157, 21))
|
||||
|
||||
declare function fb2<const T extends readonly unknown[]>(...args: T): T;
|
||||
>fb2 : Symbol(fb2, Decl(typeParameterConstModifiers.ts, 157, 63))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 158, 21))
|
||||
>args : Symbol(args, Decl(typeParameterConstModifiers.ts, 158, 57))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 158, 21))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 158, 21))
|
||||
|
||||
fb1("hello", 42);
|
||||
>fb1 : Symbol(fb1, Decl(typeParameterConstModifiers.ts, 155, 19))
|
||||
|
||||
fb2("hello", 42);
|
||||
>fb2 : Symbol(fb2, Decl(typeParameterConstModifiers.ts, 157, 63))
|
||||
|
||||
declare function fc1<const T extends unknown[]>(f: (...args: T) => void, ...args: T): T;
|
||||
>fc1 : Symbol(fc1, Decl(typeParameterConstModifiers.ts, 161, 17))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 163, 21))
|
||||
>f : Symbol(f, Decl(typeParameterConstModifiers.ts, 163, 48))
|
||||
>args : Symbol(args, Decl(typeParameterConstModifiers.ts, 163, 52))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 163, 21))
|
||||
>args : Symbol(args, Decl(typeParameterConstModifiers.ts, 163, 72))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 163, 21))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 163, 21))
|
||||
|
||||
declare function fc2<const T extends readonly unknown[]>(f: (...args: T) => void, ...args: T): T;
|
||||
>fc2 : Symbol(fc2, Decl(typeParameterConstModifiers.ts, 163, 88))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 164, 21))
|
||||
>f : Symbol(f, Decl(typeParameterConstModifiers.ts, 164, 57))
|
||||
>args : Symbol(args, Decl(typeParameterConstModifiers.ts, 164, 61))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 164, 21))
|
||||
>args : Symbol(args, Decl(typeParameterConstModifiers.ts, 164, 81))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 164, 21))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 164, 21))
|
||||
|
||||
fc1((a: string, b: number) => {}, "hello", 42);
|
||||
>fc1 : Symbol(fc1, Decl(typeParameterConstModifiers.ts, 161, 17))
|
||||
>a : Symbol(a, Decl(typeParameterConstModifiers.ts, 166, 5))
|
||||
>b : Symbol(b, Decl(typeParameterConstModifiers.ts, 166, 15))
|
||||
|
||||
fc2((a: string, b: number) => {}, "hello", 42);
|
||||
>fc2 : Symbol(fc2, Decl(typeParameterConstModifiers.ts, 163, 88))
|
||||
>a : Symbol(a, Decl(typeParameterConstModifiers.ts, 167, 5))
|
||||
>b : Symbol(b, Decl(typeParameterConstModifiers.ts, 167, 15))
|
||||
|
||||
declare function fd1<const T extends string[] | number[]>(args: T): T;
|
||||
>fd1 : Symbol(fd1, Decl(typeParameterConstModifiers.ts, 167, 47))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 169, 21))
|
||||
>args : Symbol(args, Decl(typeParameterConstModifiers.ts, 169, 58))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 169, 21))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 169, 21))
|
||||
|
||||
declare function fd2<const T extends string[] | readonly number[]>(args: T): T;
|
||||
>fd2 : Symbol(fd2, Decl(typeParameterConstModifiers.ts, 169, 70))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 170, 21))
|
||||
>args : Symbol(args, Decl(typeParameterConstModifiers.ts, 170, 67))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 170, 21))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 170, 21))
|
||||
|
||||
declare function fd3<const T extends readonly string[] | readonly number[]>(args: T): T;
|
||||
>fd3 : Symbol(fd3, Decl(typeParameterConstModifiers.ts, 170, 79))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 171, 21))
|
||||
>args : Symbol(args, Decl(typeParameterConstModifiers.ts, 171, 76))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 171, 21))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 171, 21))
|
||||
|
||||
fd1(["hello", "world"]);
|
||||
>fd1 : Symbol(fd1, Decl(typeParameterConstModifiers.ts, 167, 47))
|
||||
|
||||
fd1([1, 2, 3]);
|
||||
>fd1 : Symbol(fd1, Decl(typeParameterConstModifiers.ts, 167, 47))
|
||||
|
||||
fd2(["hello", "world"]);
|
||||
>fd2 : Symbol(fd2, Decl(typeParameterConstModifiers.ts, 169, 70))
|
||||
|
||||
fd2([1, 2, 3]);
|
||||
>fd2 : Symbol(fd2, Decl(typeParameterConstModifiers.ts, 169, 70))
|
||||
|
||||
fd3(["hello", "world"]);
|
||||
>fd3 : Symbol(fd3, Decl(typeParameterConstModifiers.ts, 170, 79))
|
||||
|
||||
fd3([1, 2, 3]);
|
||||
>fd3 : Symbol(fd3, Decl(typeParameterConstModifiers.ts, 170, 79))
|
||||
|
||||
declare function fn1<const T extends { foo: unknown[] }[]>(...args: T): T;
|
||||
>fn1 : Symbol(fn1, Decl(typeParameterConstModifiers.ts, 178, 15))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 180, 21))
|
||||
>foo : Symbol(foo, Decl(typeParameterConstModifiers.ts, 180, 38))
|
||||
>args : Symbol(args, Decl(typeParameterConstModifiers.ts, 180, 59))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 180, 21))
|
||||
>T : Symbol(T, Decl(typeParameterConstModifiers.ts, 180, 21))
|
||||
|
||||
fn1({ foo: ["hello", 123] }, { foo: [true]});
|
||||
>fn1 : Symbol(fn1, Decl(typeParameterConstModifiers.ts, 178, 15))
|
||||
>foo : Symbol(foo, Decl(typeParameterConstModifiers.ts, 182, 5))
|
||||
>foo : Symbol(foo, Decl(typeParameterConstModifiers.ts, 182, 30))
|
||||
|
||||
|
||||
@@ -409,3 +409,302 @@ 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"
|
||||
|
||||
);
|
||||
|
||||
// Same with non-readonly constraint
|
||||
|
||||
function factory_55033_2<const T extends unknown[]>(cb: (...args: T) => void) {
|
||||
>factory_55033_2 : <const T extends 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_2 = factory_55033_2((a: { test: number }, b: string) => {})(
|
||||
>t1_55033_2 : [{ readonly test: 123; }, "some string"]
|
||||
>factory_55033_2((a: { test: number }, b: string) => {})( { test: 123 }, "some string") : [{ readonly test: 123; }, "some string"]
|
||||
>factory_55033_2((a: { test: number }, b: string) => {}) : <const K extends [a: { test: number; }, b: string]>(...args: K) => K
|
||||
>factory_55033_2 : <const T extends 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_2 = factory_55033_2((a: { test: number }, b: string) => {})(
|
||||
>t2_55033_2 : [{ readonly test: 123; }, "some string"]
|
||||
>factory_55033_2((a: { test: number }, b: string) => {})( { test: 123 } as const, "some string") : [{ readonly test: 123; }, "some string"]
|
||||
>factory_55033_2((a: { test: number }, b: string) => {}) : <const K extends [a: { test: number; }, b: string]>(...args: K) => K
|
||||
>factory_55033_2 : <const T extends 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"
|
||||
|
||||
);
|
||||
|
||||
// Repro from https://github.com/microsoft/TypeScript/issues/51931
|
||||
|
||||
declare function fn<const T extends any[]>(...args: T): T;
|
||||
>fn : <const T extends any[]>(...args: T) => T
|
||||
>args : T
|
||||
|
||||
const a = fn("a", false);
|
||||
>a : ["a", false]
|
||||
>fn("a", false) : ["a", false]
|
||||
>fn : <const T extends any[]>(...args: T) => T
|
||||
>"a" : "a"
|
||||
>false : false
|
||||
|
||||
// More examples of non-readonly constraints
|
||||
|
||||
declare function fa1<const T extends unknown[]>(args: T): T;
|
||||
>fa1 : <const T extends unknown[]>(args: T) => T
|
||||
>args : T
|
||||
|
||||
declare function fa2<const T extends readonly unknown[]>(args: T): T;
|
||||
>fa2 : <const T extends readonly unknown[]>(args: T) => T
|
||||
>args : T
|
||||
|
||||
fa1(["hello", 42]);
|
||||
>fa1(["hello", 42]) : ["hello", 42]
|
||||
>fa1 : <const T extends unknown[]>(args: T) => T
|
||||
>["hello", 42] : ["hello", 42]
|
||||
>"hello" : "hello"
|
||||
>42 : 42
|
||||
|
||||
fa2(["hello", 42]);
|
||||
>fa2(["hello", 42]) : readonly ["hello", 42]
|
||||
>fa2 : <const T extends readonly unknown[]>(args: T) => T
|
||||
>["hello", 42] : ["hello", 42]
|
||||
>"hello" : "hello"
|
||||
>42 : 42
|
||||
|
||||
declare function fb1<const T extends unknown[]>(...args: T): T;
|
||||
>fb1 : <const T extends unknown[]>(...args: T) => T
|
||||
>args : T
|
||||
|
||||
declare function fb2<const T extends readonly unknown[]>(...args: T): T;
|
||||
>fb2 : <const T extends readonly unknown[]>(...args: T) => T
|
||||
>args : T
|
||||
|
||||
fb1("hello", 42);
|
||||
>fb1("hello", 42) : ["hello", 42]
|
||||
>fb1 : <const T extends unknown[]>(...args: T) => T
|
||||
>"hello" : "hello"
|
||||
>42 : 42
|
||||
|
||||
fb2("hello", 42);
|
||||
>fb2("hello", 42) : readonly ["hello", 42]
|
||||
>fb2 : <const T extends readonly unknown[]>(...args: T) => T
|
||||
>"hello" : "hello"
|
||||
>42 : 42
|
||||
|
||||
declare function fc1<const T extends unknown[]>(f: (...args: T) => void, ...args: T): T;
|
||||
>fc1 : <const T extends unknown[]>(f: (...args: T) => void, ...args: T) => T
|
||||
>f : (...args: T) => void
|
||||
>args : T
|
||||
>args : T
|
||||
|
||||
declare function fc2<const T extends readonly unknown[]>(f: (...args: T) => void, ...args: T): T;
|
||||
>fc2 : <const T extends readonly unknown[]>(f: (...args: T) => void, ...args: T) => T
|
||||
>f : (...args: T) => void
|
||||
>args : T
|
||||
>args : T
|
||||
|
||||
fc1((a: string, b: number) => {}, "hello", 42);
|
||||
>fc1((a: string, b: number) => {}, "hello", 42) : ["hello", 42]
|
||||
>fc1 : <const T extends unknown[]>(f: (...args: T) => void, ...args: T) => T
|
||||
>(a: string, b: number) => {} : (a: string, b: number) => void
|
||||
>a : string
|
||||
>b : number
|
||||
>"hello" : "hello"
|
||||
>42 : 42
|
||||
|
||||
fc2((a: string, b: number) => {}, "hello", 42);
|
||||
>fc2((a: string, b: number) => {}, "hello", 42) : readonly ["hello", 42]
|
||||
>fc2 : <const T extends readonly unknown[]>(f: (...args: T) => void, ...args: T) => T
|
||||
>(a: string, b: number) => {} : (a: string, b: number) => void
|
||||
>a : string
|
||||
>b : number
|
||||
>"hello" : "hello"
|
||||
>42 : 42
|
||||
|
||||
declare function fd1<const T extends string[] | number[]>(args: T): T;
|
||||
>fd1 : <const T extends string[] | number[]>(args: T) => T
|
||||
>args : T
|
||||
|
||||
declare function fd2<const T extends string[] | readonly number[]>(args: T): T;
|
||||
>fd2 : <const T extends string[] | readonly number[]>(args: T) => T
|
||||
>args : T
|
||||
|
||||
declare function fd3<const T extends readonly string[] | readonly number[]>(args: T): T;
|
||||
>fd3 : <const T extends readonly string[] | readonly number[]>(args: T) => T
|
||||
>args : T
|
||||
|
||||
fd1(["hello", "world"]);
|
||||
>fd1(["hello", "world"]) : ["hello", "world"]
|
||||
>fd1 : <const T extends string[] | number[]>(args: T) => T
|
||||
>["hello", "world"] : ["hello", "world"]
|
||||
>"hello" : "hello"
|
||||
>"world" : "world"
|
||||
|
||||
fd1([1, 2, 3]);
|
||||
>fd1([1, 2, 3]) : [1, 2, 3]
|
||||
>fd1 : <const T extends string[] | number[]>(args: T) => T
|
||||
>[1, 2, 3] : [1, 2, 3]
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
>3 : 3
|
||||
|
||||
fd2(["hello", "world"]);
|
||||
>fd2(["hello", "world"]) : ["hello", "world"]
|
||||
>fd2 : <const T extends string[] | readonly number[]>(args: T) => T
|
||||
>["hello", "world"] : ["hello", "world"]
|
||||
>"hello" : "hello"
|
||||
>"world" : "world"
|
||||
|
||||
fd2([1, 2, 3]);
|
||||
>fd2([1, 2, 3]) : [1, 2, 3]
|
||||
>fd2 : <const T extends string[] | readonly number[]>(args: T) => T
|
||||
>[1, 2, 3] : [1, 2, 3]
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
>3 : 3
|
||||
|
||||
fd3(["hello", "world"]);
|
||||
>fd3(["hello", "world"]) : readonly ["hello", "world"]
|
||||
>fd3 : <const T extends readonly string[] | readonly number[]>(args: T) => T
|
||||
>["hello", "world"] : ["hello", "world"]
|
||||
>"hello" : "hello"
|
||||
>"world" : "world"
|
||||
|
||||
fd3([1, 2, 3]);
|
||||
>fd3([1, 2, 3]) : readonly [1, 2, 3]
|
||||
>fd3 : <const T extends readonly string[] | readonly number[]>(args: T) => T
|
||||
>[1, 2, 3] : [1, 2, 3]
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
>3 : 3
|
||||
|
||||
declare function fn1<const T extends { foo: unknown[] }[]>(...args: T): T;
|
||||
>fn1 : <const T extends { foo: unknown[]; }[]>(...args: T) => T
|
||||
>foo : unknown[]
|
||||
>args : T
|
||||
|
||||
fn1({ foo: ["hello", 123] }, { foo: [true]});
|
||||
>fn1({ foo: ["hello", 123] }, { foo: [true]}) : [{ readonly foo: ["hello", 123]; }, { readonly foo: [true]; }]
|
||||
>fn1 : <const T extends { foo: unknown[]; }[]>(...args: T) => T
|
||||
>{ foo: ["hello", 123] } : { foo: ["hello", 123]; }
|
||||
>foo : ["hello", 123]
|
||||
>["hello", 123] : ["hello", 123]
|
||||
>"hello" : "hello"
|
||||
>123 : 123
|
||||
>{ foo: [true]} : { foo: [true]; }
|
||||
>foo : [true]
|
||||
>[true] : [true]
|
||||
>true : true
|
||||
|
||||
|
||||
@@ -100,3 +100,86 @@ 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"
|
||||
);
|
||||
|
||||
// Same with non-readonly constraint
|
||||
|
||||
function factory_55033_2<const T extends unknown[]>(cb: (...args: T) => void) {
|
||||
return function call<const K extends T>(...args: K): K {
|
||||
return {} as K;
|
||||
};
|
||||
}
|
||||
|
||||
const t1_55033_2 = factory_55033_2((a: { test: number }, b: string) => {})(
|
||||
{ test: 123 },
|
||||
"some string"
|
||||
);
|
||||
|
||||
const t2_55033_2 = factory_55033_2((a: { test: number }, b: string) => {})(
|
||||
{ test: 123 } as const,
|
||||
"some string"
|
||||
);
|
||||
|
||||
// Repro from https://github.com/microsoft/TypeScript/issues/51931
|
||||
|
||||
declare function fn<const T extends any[]>(...args: T): T;
|
||||
|
||||
const a = fn("a", false);
|
||||
|
||||
// More examples of non-readonly constraints
|
||||
|
||||
declare function fa1<const T extends unknown[]>(args: T): T;
|
||||
declare function fa2<const T extends readonly unknown[]>(args: T): T;
|
||||
|
||||
fa1(["hello", 42]);
|
||||
fa2(["hello", 42]);
|
||||
|
||||
declare function fb1<const T extends unknown[]>(...args: T): T;
|
||||
declare function fb2<const T extends readonly unknown[]>(...args: T): T;
|
||||
|
||||
fb1("hello", 42);
|
||||
fb2("hello", 42);
|
||||
|
||||
declare function fc1<const T extends unknown[]>(f: (...args: T) => void, ...args: T): T;
|
||||
declare function fc2<const T extends readonly unknown[]>(f: (...args: T) => void, ...args: T): T;
|
||||
|
||||
fc1((a: string, b: number) => {}, "hello", 42);
|
||||
fc2((a: string, b: number) => {}, "hello", 42);
|
||||
|
||||
declare function fd1<const T extends string[] | number[]>(args: T): T;
|
||||
declare function fd2<const T extends string[] | readonly number[]>(args: T): T;
|
||||
declare function fd3<const T extends readonly string[] | readonly number[]>(args: T): T;
|
||||
|
||||
fd1(["hello", "world"]);
|
||||
fd1([1, 2, 3]);
|
||||
fd2(["hello", "world"]);
|
||||
fd2([1, 2, 3]);
|
||||
fd3(["hello", "world"]);
|
||||
fd3([1, 2, 3]);
|
||||
|
||||
declare function fn1<const T extends { foo: unknown[] }[]>(...args: T): T;
|
||||
|
||||
fn1({ foo: ["hello", 123] }, { foo: [true]});
|
||||
|
||||
Reference in New Issue
Block a user