Extend isTupleLikeType to also check if .length is a number literal type (#52617)

This commit is contained in:
Mateusz Burzyński
2023-06-30 04:13:02 +02:00
committed by GitHub
parent 34f6e107a3
commit 3073b5209b
6 changed files with 92 additions and 4 deletions

View File

@@ -23303,7 +23303,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
function isTupleLikeType(type: Type): boolean {
return isTupleType(type) || !!getPropertyOfType(type, "0" as __String);
let lengthType;
return isTupleType(type) ||
!!getPropertyOfType(type, "0" as __String) ||
isArrayLikeType(type) && !!(lengthType = getTypeOfPropertyOfType(type, "length" as __String)) && everyType(lengthType, t => !!(t.flags & TypeFlags.NumberLiteral));
}
function isArrayOrTupleLikeType(type: Type): boolean {

View File

@@ -68,4 +68,15 @@ contextualTypeWithTuple.ts(25,1): error TS2322: Type '[number, string | number]'
!!! error TS2322: Type '[number, string | number]' is not assignable to type '[number, string]'.
!!! error TS2322: Type at position 1 in source is not compatible with type at position 1 in target.
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
// repro from #29311
type test1 = [...number[]]
type fixed1 = test1 & { length: 2 }
let var1: fixed1 = [0, 0]
// #52551
type EmptyTuple = []
interface MyEmptyTuple extends EmptyTuple { extraInfo?: any; }
const withExtra: MyEmptyTuple = []

View File

@@ -25,7 +25,18 @@ var strStrTuple: [string, string] = ["foo", "bar", 5];
unionTuple = unionTuple1;
unionTuple = unionTuple2;
unionTuple2 = unionTuple;
numStrTuple = unionTuple3;
numStrTuple = unionTuple3;
// repro from #29311
type test1 = [...number[]]
type fixed1 = test1 & { length: 2 }
let var1: fixed1 = [0, 0]
// #52551
type EmptyTuple = []
interface MyEmptyTuple extends EmptyTuple { extraInfo?: any; }
const withExtra: MyEmptyTuple = []
//// [contextualTypeWithTuple.js]
// no error
@@ -58,3 +69,5 @@ unionTuple = unionTuple1;
unionTuple = unionTuple2;
unionTuple2 = unionTuple;
numStrTuple = unionTuple3;
var var1 = [0, 0];
var withExtra = [];

View File

@@ -82,3 +82,29 @@ numStrTuple = unionTuple3;
>numStrTuple : Symbol(numStrTuple, Decl(contextualTypeWithTuple.ts, 1, 3))
>unionTuple3 : Symbol(unionTuple3, Decl(contextualTypeWithTuple.ts, 11, 3))
// repro from #29311
type test1 = [...number[]]
>test1 : Symbol(test1, Decl(contextualTypeWithTuple.ts, 24, 26))
type fixed1 = test1 & { length: 2 }
>fixed1 : Symbol(fixed1, Decl(contextualTypeWithTuple.ts, 27, 26))
>test1 : Symbol(test1, Decl(contextualTypeWithTuple.ts, 24, 26))
>length : Symbol(length, Decl(contextualTypeWithTuple.ts, 28, 23))
let var1: fixed1 = [0, 0]
>var1 : Symbol(var1, Decl(contextualTypeWithTuple.ts, 29, 3))
>fixed1 : Symbol(fixed1, Decl(contextualTypeWithTuple.ts, 27, 26))
// #52551
type EmptyTuple = []
>EmptyTuple : Symbol(EmptyTuple, Decl(contextualTypeWithTuple.ts, 29, 25))
interface MyEmptyTuple extends EmptyTuple { extraInfo?: any; }
>MyEmptyTuple : Symbol(MyEmptyTuple, Decl(contextualTypeWithTuple.ts, 32, 20))
>EmptyTuple : Symbol(EmptyTuple, Decl(contextualTypeWithTuple.ts, 29, 25))
>extraInfo : Symbol(MyEmptyTuple.extraInfo, Decl(contextualTypeWithTuple.ts, 33, 43))
const withExtra: MyEmptyTuple = []
>withExtra : Symbol(withExtra, Decl(contextualTypeWithTuple.ts, 34, 5))
>MyEmptyTuple : Symbol(MyEmptyTuple, Decl(contextualTypeWithTuple.ts, 32, 20))

View File

@@ -128,3 +128,28 @@ numStrTuple = unionTuple3;
>numStrTuple : [number, string]
>unionTuple3 : [number, string | number]
// repro from #29311
type test1 = [...number[]]
>test1 : number[]
type fixed1 = test1 & { length: 2 }
>fixed1 : test1 & { length: 2; }
>length : 2
let var1: fixed1 = [0, 0]
>var1 : fixed1
>[0, 0] : [number, number]
>0 : 0
>0 : 0
// #52551
type EmptyTuple = []
>EmptyTuple : []
interface MyEmptyTuple extends EmptyTuple { extraInfo?: any; }
>extraInfo : any
const withExtra: MyEmptyTuple = []
>withExtra : MyEmptyTuple
>[] : []

View File

@@ -22,4 +22,14 @@ var strStrTuple: [string, string] = ["foo", "bar", 5];
unionTuple = unionTuple1;
unionTuple = unionTuple2;
unionTuple2 = unionTuple;
numStrTuple = unionTuple3;
numStrTuple = unionTuple3;
// repro from #29311
type test1 = [...number[]]
type fixed1 = test1 & { length: 2 }
let var1: fixed1 = [0, 0]
// #52551
type EmptyTuple = []
interface MyEmptyTuple extends EmptyTuple { extraInfo?: any; }
const withExtra: MyEmptyTuple = []