Fixed issues with inference from nested tuple types of the same shape (#49226)

This commit is contained in:
Mateusz Burzyński 2023-03-20 19:18:08 +01:00 committed by GitHub
parent 9e1f0adf61
commit 3fab5fff34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 209 additions and 2 deletions

View File

@ -22888,8 +22888,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return type.symbol;
}
if (isTupleType(type)) {
// Tuple types are tracked through their target type
return type.target;
return type;
}
}
if (type.flags & TypeFlags.TypeParameter) {

View File

@ -0,0 +1,86 @@
=== tests/cases/compiler/inferFromNestedSameShapeTuple.ts ===
// repro #48524
type Magic<X> = X extends [[infer Y, ...infer _], ...infer __] ? Y : never;
>Magic : Symbol(Magic, Decl(inferFromNestedSameShapeTuple.ts, 0, 0))
>X : Symbol(X, Decl(inferFromNestedSameShapeTuple.ts, 2, 11))
>X : Symbol(X, Decl(inferFromNestedSameShapeTuple.ts, 2, 11))
>Y : Symbol(Y, Decl(inferFromNestedSameShapeTuple.ts, 2, 33))
>_ : Symbol(_, Decl(inferFromNestedSameShapeTuple.ts, 2, 45))
>__ : Symbol(__, Decl(inferFromNestedSameShapeTuple.ts, 2, 58))
>Y : Symbol(Y, Decl(inferFromNestedSameShapeTuple.ts, 2, 33))
type R = Magic<[[number]]>
>R : Symbol(R, Decl(inferFromNestedSameShapeTuple.ts, 2, 75))
>Magic : Symbol(Magic, Decl(inferFromNestedSameShapeTuple.ts, 0, 0))
// repro #52722
type Recursive<Id> = {
>Recursive : Symbol(Recursive, Decl(inferFromNestedSameShapeTuple.ts, 4, 26))
>Id : Symbol(Id, Decl(inferFromNestedSameShapeTuple.ts, 8, 15))
id: Id
>id : Symbol(id, Decl(inferFromNestedSameShapeTuple.ts, 8, 22))
>Id : Symbol(Id, Decl(inferFromNestedSameShapeTuple.ts, 8, 15))
children: readonly Recursive<Id>[]
>children : Symbol(children, Decl(inferFromNestedSameShapeTuple.ts, 9, 10))
>Recursive : Symbol(Recursive, Decl(inferFromNestedSameShapeTuple.ts, 4, 26))
>Id : Symbol(Id, Decl(inferFromNestedSameShapeTuple.ts, 8, 15))
}
declare function getIds<Id>(items: readonly Recursive<Id>[]): Id[];
>getIds : Symbol(getIds, Decl(inferFromNestedSameShapeTuple.ts, 11, 1))
>Id : Symbol(Id, Decl(inferFromNestedSameShapeTuple.ts, 13, 24))
>items : Symbol(items, Decl(inferFromNestedSameShapeTuple.ts, 13, 28))
>Recursive : Symbol(Recursive, Decl(inferFromNestedSameShapeTuple.ts, 4, 26))
>Id : Symbol(Id, Decl(inferFromNestedSameShapeTuple.ts, 13, 24))
>Id : Symbol(Id, Decl(inferFromNestedSameShapeTuple.ts, 13, 24))
const items = [{
>items : Symbol(items, Decl(inferFromNestedSameShapeTuple.ts, 15, 5))
id: 'a',
>id : Symbol(id, Decl(inferFromNestedSameShapeTuple.ts, 15, 16))
children: [{
>children : Symbol(children, Decl(inferFromNestedSameShapeTuple.ts, 16, 12))
id: 'b',
>id : Symbol(id, Decl(inferFromNestedSameShapeTuple.ts, 17, 16))
children: []
>children : Symbol(children, Decl(inferFromNestedSameShapeTuple.ts, 18, 16))
}]
}] as const satisfies readonly Recursive<string>[]
>const : Symbol(const)
>Recursive : Symbol(Recursive, Decl(inferFromNestedSameShapeTuple.ts, 4, 26))
const foo = getIds(items)
>foo : Symbol(foo, Decl(inferFromNestedSameShapeTuple.ts, 23, 5))
>getIds : Symbol(getIds, Decl(inferFromNestedSameShapeTuple.ts, 11, 1))
>items : Symbol(items, Decl(inferFromNestedSameShapeTuple.ts, 15, 5))
// variant with a fresh argument
const foo2 = getIds([{
>foo2 : Symbol(foo2, Decl(inferFromNestedSameShapeTuple.ts, 26, 5))
>getIds : Symbol(getIds, Decl(inferFromNestedSameShapeTuple.ts, 11, 1))
id: 'a',
>id : Symbol(id, Decl(inferFromNestedSameShapeTuple.ts, 26, 22))
children: [{
>children : Symbol(children, Decl(inferFromNestedSameShapeTuple.ts, 27, 12))
id: 'b',
>id : Symbol(id, Decl(inferFromNestedSameShapeTuple.ts, 28, 16))
children: []
>children : Symbol(children, Decl(inferFromNestedSameShapeTuple.ts, 29, 16))
}]
}] as const)
>const : Symbol(const)

View File

@ -0,0 +1,86 @@
=== tests/cases/compiler/inferFromNestedSameShapeTuple.ts ===
// repro #48524
type Magic<X> = X extends [[infer Y, ...infer _], ...infer __] ? Y : never;
>Magic : Magic<X>
type R = Magic<[[number]]>
>R : number
// repro #52722
type Recursive<Id> = {
>Recursive : Recursive<Id>
id: Id
>id : Id
children: readonly Recursive<Id>[]
>children : readonly Recursive<Id>[]
}
declare function getIds<Id>(items: readonly Recursive<Id>[]): Id[];
>getIds : <Id>(items: readonly Recursive<Id>[]) => Id[]
>items : readonly Recursive<Id>[]
const items = [{
>items : readonly [{ readonly id: "a"; readonly children: readonly [{ readonly id: "b"; readonly children: readonly []; }]; }]
>[{ id: 'a', children: [{ id: 'b', children: [] }]}] as const satisfies readonly Recursive<string>[] : readonly [{ readonly id: "a"; readonly children: readonly [{ readonly id: "b"; readonly children: readonly []; }]; }]
>[{ id: 'a', children: [{ id: 'b', children: [] }]}] as const : readonly [{ readonly id: "a"; readonly children: readonly [{ readonly id: "b"; readonly children: readonly []; }]; }]
>[{ id: 'a', children: [{ id: 'b', children: [] }]}] : readonly [{ readonly id: "a"; readonly children: readonly [{ readonly id: "b"; readonly children: readonly []; }]; }]
>{ id: 'a', children: [{ id: 'b', children: [] }]} : { readonly id: "a"; readonly children: readonly [{ readonly id: "b"; readonly children: readonly []; }]; }
id: 'a',
>id : "a"
>'a' : "a"
children: [{
>children : readonly [{ readonly id: "b"; readonly children: readonly []; }]
>[{ id: 'b', children: [] }] : readonly [{ readonly id: "b"; readonly children: readonly []; }]
>{ id: 'b', children: [] } : { readonly id: "b"; readonly children: readonly []; }
id: 'b',
>id : "b"
>'b' : "b"
children: []
>children : readonly []
>[] : readonly []
}]
}] as const satisfies readonly Recursive<string>[]
const foo = getIds(items)
>foo : ("a" | "b")[]
>getIds(items) : ("a" | "b")[]
>getIds : <Id>(items: readonly Recursive<Id>[]) => Id[]
>items : readonly [{ readonly id: "a"; readonly children: readonly [{ readonly id: "b"; readonly children: readonly []; }]; }]
// variant with a fresh argument
const foo2 = getIds([{
>foo2 : ("a" | "b")[]
>getIds([{ id: 'a', children: [{ id: 'b', children: [] }]}] as const) : ("a" | "b")[]
>getIds : <Id>(items: readonly Recursive<Id>[]) => Id[]
>[{ id: 'a', children: [{ id: 'b', children: [] }]}] as const : readonly [{ readonly id: "a"; readonly children: readonly [{ readonly id: "b"; readonly children: readonly []; }]; }]
>[{ id: 'a', children: [{ id: 'b', children: [] }]}] : readonly [{ readonly id: "a"; readonly children: readonly [{ readonly id: "b"; readonly children: readonly []; }]; }]
>{ id: 'a', children: [{ id: 'b', children: [] }]} : { readonly id: "a"; readonly children: readonly [{ readonly id: "b"; readonly children: readonly []; }]; }
id: 'a',
>id : "a"
>'a' : "a"
children: [{
>children : readonly [{ readonly id: "b"; readonly children: readonly []; }]
>[{ id: 'b', children: [] }] : readonly [{ readonly id: "b"; readonly children: readonly []; }]
>{ id: 'b', children: [] } : { readonly id: "b"; readonly children: readonly []; }
id: 'b',
>id : "b"
>'b' : "b"
children: []
>children : readonly []
>[] : readonly []
}]
}] as const)

View File

@ -0,0 +1,36 @@
// @strict: true
// @noEmit: true
// repro #48524
type Magic<X> = X extends [[infer Y, ...infer _], ...infer __] ? Y : never;
type R = Magic<[[number]]>
// repro #52722
type Recursive<Id> = {
id: Id
children: readonly Recursive<Id>[]
}
declare function getIds<Id>(items: readonly Recursive<Id>[]): Id[];
const items = [{
id: 'a',
children: [{
id: 'b',
children: []
}]
}] as const satisfies readonly Recursive<string>[]
const foo = getIds(items)
// variant with a fresh argument
const foo2 = getIds([{
id: 'a',
children: [{
id: 'b',
children: []
}]
}] as const)