mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-04-17 13:48:46 -05:00
Ensure rest type for source parameter is readonly in relations (#53258)
This commit is contained in:
@@ -19850,7 +19850,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const restIndex = sourceRestType || targetRestType ? paramCount - 1 : -1;
|
||||
|
||||
for (let i = 0; i < paramCount; i++) {
|
||||
const sourceType = i === restIndex ? getRestTypeAtPosition(source, i) : tryGetTypeAtPosition(source, i);
|
||||
const sourceType = i === restIndex ? getRestTypeAtPosition(source, i, /*readonly*/ true) : tryGetTypeAtPosition(source, i);
|
||||
const targetType = i === restIndex ? getRestTypeAtPosition(target, i) : tryGetTypeAtPosition(target, i);
|
||||
if (sourceType && targetType) {
|
||||
// In order to ensure that any generic type Foo<T> is at least co-variant with respect to T no matter
|
||||
@@ -34656,12 +34656,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getRestTypeAtPosition(source: Signature, pos: number): Type {
|
||||
function getRestTypeAtPosition(source: Signature, pos: number, readonly = false): Type {
|
||||
const parameterCount = getParameterCount(source);
|
||||
const minArgumentCount = getMinArgumentCount(source);
|
||||
const restType = getEffectiveRestType(source);
|
||||
if (restType && pos >= parameterCount - 1) {
|
||||
return pos === parameterCount - 1 ? restType : createArrayType(getIndexedAccessType(restType, numberType));
|
||||
return pos === parameterCount - 1 ? restType : createArrayType(getIndexedAccessType(restType, numberType), readonly);
|
||||
}
|
||||
const types = [];
|
||||
const flags = [];
|
||||
@@ -34680,7 +34680,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
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
//// [contextualTupleTypeParameterReadonly.ts]
|
||||
declare function each<T extends ReadonlyArray<any>>(cases: ReadonlyArray<T>): (fn: (...args: T) => any) => void;
|
||||
|
||||
const cases = [
|
||||
[1, '1'],
|
||||
[2, '2'],
|
||||
] as const;
|
||||
|
||||
const eacher = each(cases);
|
||||
|
||||
eacher((a, b) => {
|
||||
a;
|
||||
b;
|
||||
});
|
||||
|
||||
eacher((...args) => {
|
||||
const [a, b] = args;
|
||||
a;
|
||||
b;
|
||||
});
|
||||
|
||||
|
||||
//// [contextualTupleTypeParameterReadonly.js]
|
||||
"use strict";
|
||||
var cases = [
|
||||
[1, '1'],
|
||||
[2, '2'],
|
||||
];
|
||||
var eacher = each(cases);
|
||||
eacher(function (a, b) {
|
||||
a;
|
||||
b;
|
||||
});
|
||||
eacher(function () {
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
var a = args[0], b = args[1];
|
||||
a;
|
||||
b;
|
||||
});
|
||||
@@ -0,0 +1,55 @@
|
||||
=== tests/cases/compiler/contextualTupleTypeParameterReadonly.ts ===
|
||||
declare function each<T extends ReadonlyArray<any>>(cases: ReadonlyArray<T>): (fn: (...args: T) => any) => void;
|
||||
>each : Symbol(each, Decl(contextualTupleTypeParameterReadonly.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(contextualTupleTypeParameterReadonly.ts, 0, 22))
|
||||
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --))
|
||||
>cases : Symbol(cases, Decl(contextualTupleTypeParameterReadonly.ts, 0, 52))
|
||||
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(contextualTupleTypeParameterReadonly.ts, 0, 22))
|
||||
>fn : Symbol(fn, Decl(contextualTupleTypeParameterReadonly.ts, 0, 79))
|
||||
>args : Symbol(args, Decl(contextualTupleTypeParameterReadonly.ts, 0, 84))
|
||||
>T : Symbol(T, Decl(contextualTupleTypeParameterReadonly.ts, 0, 22))
|
||||
|
||||
const cases = [
|
||||
>cases : Symbol(cases, Decl(contextualTupleTypeParameterReadonly.ts, 2, 5))
|
||||
|
||||
[1, '1'],
|
||||
[2, '2'],
|
||||
] as const;
|
||||
>const : Symbol(const)
|
||||
|
||||
const eacher = each(cases);
|
||||
>eacher : Symbol(eacher, Decl(contextualTupleTypeParameterReadonly.ts, 7, 5))
|
||||
>each : Symbol(each, Decl(contextualTupleTypeParameterReadonly.ts, 0, 0))
|
||||
>cases : Symbol(cases, Decl(contextualTupleTypeParameterReadonly.ts, 2, 5))
|
||||
|
||||
eacher((a, b) => {
|
||||
>eacher : Symbol(eacher, Decl(contextualTupleTypeParameterReadonly.ts, 7, 5))
|
||||
>a : Symbol(a, Decl(contextualTupleTypeParameterReadonly.ts, 9, 8))
|
||||
>b : Symbol(b, Decl(contextualTupleTypeParameterReadonly.ts, 9, 10))
|
||||
|
||||
a;
|
||||
>a : Symbol(a, Decl(contextualTupleTypeParameterReadonly.ts, 9, 8))
|
||||
|
||||
b;
|
||||
>b : Symbol(b, Decl(contextualTupleTypeParameterReadonly.ts, 9, 10))
|
||||
|
||||
});
|
||||
|
||||
eacher((...args) => {
|
||||
>eacher : Symbol(eacher, Decl(contextualTupleTypeParameterReadonly.ts, 7, 5))
|
||||
>args : Symbol(args, Decl(contextualTupleTypeParameterReadonly.ts, 14, 8))
|
||||
|
||||
const [a, b] = args;
|
||||
>a : Symbol(a, Decl(contextualTupleTypeParameterReadonly.ts, 15, 11))
|
||||
>b : Symbol(b, Decl(contextualTupleTypeParameterReadonly.ts, 15, 13))
|
||||
>args : Symbol(args, Decl(contextualTupleTypeParameterReadonly.ts, 14, 8))
|
||||
|
||||
a;
|
||||
>a : Symbol(a, Decl(contextualTupleTypeParameterReadonly.ts, 15, 11))
|
||||
|
||||
b;
|
||||
>b : Symbol(b, Decl(contextualTupleTypeParameterReadonly.ts, 15, 13))
|
||||
|
||||
});
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
=== tests/cases/compiler/contextualTupleTypeParameterReadonly.ts ===
|
||||
declare function each<T extends ReadonlyArray<any>>(cases: ReadonlyArray<T>): (fn: (...args: T) => any) => void;
|
||||
>each : <T extends readonly any[]>(cases: ReadonlyArray<T>) => (fn: (...args: T) => any) => void
|
||||
>cases : readonly T[]
|
||||
>fn : (...args: T) => any
|
||||
>args : T
|
||||
|
||||
const cases = [
|
||||
>cases : readonly [readonly [1, "1"], readonly [2, "2"]]
|
||||
>[ [1, '1'], [2, '2'],] as const : readonly [readonly [1, "1"], readonly [2, "2"]]
|
||||
>[ [1, '1'], [2, '2'],] : readonly [readonly [1, "1"], readonly [2, "2"]]
|
||||
|
||||
[1, '1'],
|
||||
>[1, '1'] : readonly [1, "1"]
|
||||
>1 : 1
|
||||
>'1' : "1"
|
||||
|
||||
[2, '2'],
|
||||
>[2, '2'] : readonly [2, "2"]
|
||||
>2 : 2
|
||||
>'2' : "2"
|
||||
|
||||
] as const;
|
||||
|
||||
const eacher = each(cases);
|
||||
>eacher : (fn: (...args: readonly [1, "1"] | readonly [2, "2"]) => any) => void
|
||||
>each(cases) : (fn: (...args: readonly [1, "1"] | readonly [2, "2"]) => any) => void
|
||||
>each : <T extends readonly any[]>(cases: readonly T[]) => (fn: (...args: T) => any) => void
|
||||
>cases : readonly [readonly [1, "1"], readonly [2, "2"]]
|
||||
|
||||
eacher((a, b) => {
|
||||
>eacher((a, b) => { a; b;}) : void
|
||||
>eacher : (fn: (...args: readonly [1, "1"] | readonly [2, "2"]) => any) => void
|
||||
>(a, b) => { a; b;} : (a: 1 | 2, b: "1" | "2") => void
|
||||
>a : 1 | 2
|
||||
>b : "1" | "2"
|
||||
|
||||
a;
|
||||
>a : 1 | 2
|
||||
|
||||
b;
|
||||
>b : "1" | "2"
|
||||
|
||||
});
|
||||
|
||||
eacher((...args) => {
|
||||
>eacher((...args) => { const [a, b] = args; a; b;}) : void
|
||||
>eacher : (fn: (...args: readonly [1, "1"] | readonly [2, "2"]) => any) => void
|
||||
>(...args) => { const [a, b] = args; a; b;} : (...args: readonly [1, "1"] | readonly [2, "2"]) => void
|
||||
>args : readonly [1, "1"] | readonly [2, "2"]
|
||||
|
||||
const [a, b] = args;
|
||||
>a : 1 | 2
|
||||
>b : "1" | "2"
|
||||
>args : readonly [1, "1"] | readonly [2, "2"]
|
||||
|
||||
a;
|
||||
>a : 1 | 2
|
||||
|
||||
b;
|
||||
>b : "1" | "2"
|
||||
|
||||
});
|
||||
|
||||
@@ -6,19 +6,19 @@ tests/cases/conformance/types/rest/genericRestParameters3.ts(18,1): error TS2345
|
||||
Source has 0 element(s) but target requires 2.
|
||||
tests/cases/conformance/types/rest/genericRestParameters3.ts(23,1): error TS2322: Type '(x: string, y: string) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
|
||||
Types of parameters 'y' and 'args' are incompatible.
|
||||
Type '[string] | [number, boolean]' is not assignable to type '[y: string]'.
|
||||
Type '[number, boolean]' is not assignable to type '[y: string]'.
|
||||
Type '[string] | [number, boolean]' is not assignable to type 'readonly [y: string]'.
|
||||
Type '[number, boolean]' is not assignable to type 'readonly [y: string]'.
|
||||
Source has 2 element(s) but target allows only 1.
|
||||
tests/cases/conformance/types/rest/genericRestParameters3.ts(24,1): error TS2322: Type '(x: string, y: number, z: boolean) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
|
||||
Types of parameters 'y' and 'args' are incompatible.
|
||||
Type '[string] | [number, boolean]' is not assignable to type '[y: number, z: boolean]'.
|
||||
Type '[string]' is not assignable to type '[y: number, z: boolean]'.
|
||||
Type '[string] | [number, boolean]' is not assignable to type 'readonly [y: number, z: boolean]'.
|
||||
Type '[string]' is not assignable to type 'readonly [y: number, z: boolean]'.
|
||||
Source has 1 element(s) but target requires 2.
|
||||
tests/cases/conformance/types/rest/genericRestParameters3.ts(35,1): error TS2554: Expected 1 arguments, but got 0.
|
||||
tests/cases/conformance/types/rest/genericRestParameters3.ts(36,21): error TS2345: Argument of type 'number' is not assignable to parameter of type '(...args: CoolArray<any>) => void'.
|
||||
tests/cases/conformance/types/rest/genericRestParameters3.ts(37,21): error TS2345: Argument of type '<T extends any[]>(cb: (...args: T) => void) => void' is not assignable to parameter of type '(...args: CoolArray<any>) => void'.
|
||||
Types of parameters 'cb' and 'args' are incompatible.
|
||||
Property '0' is missing in type 'CoolArray<any>' but required in type '[cb: (...args: any[]) => void]'.
|
||||
Property '0' is missing in type 'CoolArray<any>' but required in type 'readonly [cb: (...args: any[]) => void]'.
|
||||
tests/cases/conformance/types/rest/genericRestParameters3.ts(44,32): error TS2345: Argument of type '[10, 20]' is not assignable to parameter of type 'CoolArray<number>'.
|
||||
Property 'hello' is missing in type '[10, 20]' but required in type 'CoolArray<number>'.
|
||||
tests/cases/conformance/types/rest/genericRestParameters3.ts(49,1): error TS2345: Argument of type '[]' is not assignable to parameter of type 'CoolArray<never>'.
|
||||
@@ -69,15 +69,15 @@ tests/cases/conformance/types/rest/genericRestParameters3.ts(59,5): error TS2345
|
||||
~~
|
||||
!!! error TS2322: Type '(x: string, y: string) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
|
||||
!!! error TS2322: Types of parameters 'y' and 'args' are incompatible.
|
||||
!!! error TS2322: Type '[string] | [number, boolean]' is not assignable to type '[y: string]'.
|
||||
!!! error TS2322: Type '[number, boolean]' is not assignable to type '[y: string]'.
|
||||
!!! error TS2322: Type '[string] | [number, boolean]' is not assignable to type 'readonly [y: string]'.
|
||||
!!! error TS2322: Type '[number, boolean]' is not assignable to type 'readonly [y: string]'.
|
||||
!!! error TS2322: Source has 2 element(s) but target allows only 1.
|
||||
f1 = f3; // Error
|
||||
~~
|
||||
!!! error TS2322: Type '(x: string, y: number, z: boolean) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
|
||||
!!! error TS2322: Types of parameters 'y' and 'args' are incompatible.
|
||||
!!! error TS2322: Type '[string] | [number, boolean]' is not assignable to type '[y: number, z: boolean]'.
|
||||
!!! error TS2322: Type '[string]' is not assignable to type '[y: number, z: boolean]'.
|
||||
!!! error TS2322: Type '[string] | [number, boolean]' is not assignable to type 'readonly [y: number, z: boolean]'.
|
||||
!!! error TS2322: Type '[string]' is not assignable to type 'readonly [y: number, z: boolean]'.
|
||||
!!! error TS2322: Source has 1 element(s) but target requires 2.
|
||||
f1 = f4;
|
||||
|
||||
@@ -100,7 +100,7 @@ tests/cases/conformance/types/rest/genericRestParameters3.ts(59,5): error TS2345
|
||||
~~~
|
||||
!!! error TS2345: Argument of type '<T extends any[]>(cb: (...args: T) => void) => void' is not assignable to parameter of type '(...args: CoolArray<any>) => void'.
|
||||
!!! error TS2345: Types of parameters 'cb' and 'args' are incompatible.
|
||||
!!! error TS2345: Property '0' is missing in type 'CoolArray<any>' but required in type '[cb: (...args: any[]) => void]'.
|
||||
!!! error TS2345: Property '0' is missing in type 'CoolArray<any>' but required in type 'readonly [cb: (...args: any[]) => void]'.
|
||||
|
||||
function bar<T extends any[]>(...args: T): T {
|
||||
return args;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
tests/cases/conformance/types/rest/restTuplesFromContextualTypes.ts(56,7): error TS2345: Argument of type '(a: number, b: T[0], ...x: T[number][]) => void' is not assignable to parameter of type '(x: number, ...args: T) => void'.
|
||||
Types of parameters 'b' and 'args' are incompatible.
|
||||
Type 'T' is not assignable to type '[b: T[0], ...x: T[number][]]'.
|
||||
Type 'any[]' is not assignable to type '[b: T[0], ...x: T[number][]]'.
|
||||
Type 'T' is not assignable to type 'readonly [b: T[0], ...x: T[number][]]'.
|
||||
Type 'any[]' is not assignable to type 'readonly [b: T[0], ...x: T[number][]]'.
|
||||
Source provides no match for required element at position 0 in target.
|
||||
|
||||
|
||||
@@ -65,8 +65,8 @@ tests/cases/conformance/types/rest/restTuplesFromContextualTypes.ts(56,7): error
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2345: Argument of type '(a: number, b: T[0], ...x: T[number][]) => void' is not assignable to parameter of type '(x: number, ...args: T) => void'.
|
||||
!!! error TS2345: Types of parameters 'b' and 'args' are incompatible.
|
||||
!!! error TS2345: Type 'T' is not assignable to type '[b: T[0], ...x: T[number][]]'.
|
||||
!!! error TS2345: Type 'any[]' is not assignable to type '[b: T[0], ...x: T[number][]]'.
|
||||
!!! error TS2345: Type 'T' is not assignable to type 'readonly [b: T[0], ...x: T[number][]]'.
|
||||
!!! error TS2345: Type 'any[]' is not assignable to type 'readonly [b: T[0], ...x: T[number][]]'.
|
||||
!!! error TS2345: Source provides no match for required element at position 0 in target.
|
||||
}
|
||||
|
||||
|
||||
21
tests/cases/compiler/contextualTupleTypeParameterReadonly.ts
Normal file
21
tests/cases/compiler/contextualTupleTypeParameterReadonly.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
// @strict: true
|
||||
|
||||
declare function each<T extends ReadonlyArray<any>>(cases: ReadonlyArray<T>): (fn: (...args: T) => any) => void;
|
||||
|
||||
const cases = [
|
||||
[1, '1'],
|
||||
[2, '2'],
|
||||
] as const;
|
||||
|
||||
const eacher = each(cases);
|
||||
|
||||
eacher((a, b) => {
|
||||
a;
|
||||
b;
|
||||
});
|
||||
|
||||
eacher((...args) => {
|
||||
const [a, b] = args;
|
||||
a;
|
||||
b;
|
||||
});
|
||||
Reference in New Issue
Block a user