Skip to content

Commit d8ac54b

Browse files
authored
Fix substitution types of indexed access types of substitution types (microsoft#47791)
* Fix substitution types of indexed access types of substitution types * Add tests * Fix accidental unindentation
1 parent 867470c commit d8ac54b

9 files changed

+126
-1
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13506,7 +13506,7 @@ namespace ts {
1350613506

1350713507
function getImpliedConstraint(type: Type, checkNode: TypeNode, extendsNode: TypeNode): Type | undefined {
1350813508
return isUnaryTupleTypeNode(checkNode) && isUnaryTupleTypeNode(extendsNode) ? getImpliedConstraint(type, (checkNode as TupleTypeNode).elements[0], (extendsNode as TupleTypeNode).elements[0]) :
13509-
getActualTypeVariable(getTypeFromTypeNode(checkNode)) === type ? getTypeFromTypeNode(extendsNode) :
13509+
getActualTypeVariable(getTypeFromTypeNode(checkNode)) === getActualTypeVariable(type) ? getTypeFromTypeNode(extendsNode) :
1351013510
undefined;
1351113511
}
1351213512

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//// [substitutionTypeForIndexedAccessType1.ts]
2+
type AddPropToObject<Obj extends object, Prop extends string> = Prop extends keyof Obj
3+
? Obj[Prop] extends unknown[]
4+
? [...Obj[Prop]]
5+
: never
6+
: never
7+
8+
//// [substitutionTypeForIndexedAccessType1.js]
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
=== tests/cases/compiler/substitutionTypeForIndexedAccessType1.ts ===
2+
type AddPropToObject<Obj extends object, Prop extends string> = Prop extends keyof Obj
3+
>AddPropToObject : Symbol(AddPropToObject, Decl(substitutionTypeForIndexedAccessType1.ts, 0, 0))
4+
>Obj : Symbol(Obj, Decl(substitutionTypeForIndexedAccessType1.ts, 0, 21))
5+
>Prop : Symbol(Prop, Decl(substitutionTypeForIndexedAccessType1.ts, 0, 40))
6+
>Prop : Symbol(Prop, Decl(substitutionTypeForIndexedAccessType1.ts, 0, 40))
7+
>Obj : Symbol(Obj, Decl(substitutionTypeForIndexedAccessType1.ts, 0, 21))
8+
9+
? Obj[Prop] extends unknown[]
10+
>Obj : Symbol(Obj, Decl(substitutionTypeForIndexedAccessType1.ts, 0, 21))
11+
>Prop : Symbol(Prop, Decl(substitutionTypeForIndexedAccessType1.ts, 0, 40))
12+
13+
? [...Obj[Prop]]
14+
>Obj : Symbol(Obj, Decl(substitutionTypeForIndexedAccessType1.ts, 0, 21))
15+
>Prop : Symbol(Prop, Decl(substitutionTypeForIndexedAccessType1.ts, 0, 40))
16+
17+
: never
18+
: never
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
=== tests/cases/compiler/substitutionTypeForIndexedAccessType1.ts ===
2+
type AddPropToObject<Obj extends object, Prop extends string> = Prop extends keyof Obj
3+
>AddPropToObject : AddPropToObject<Obj, Prop>
4+
5+
? Obj[Prop] extends unknown[]
6+
? [...Obj[Prop]]
7+
: never
8+
: never
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//// [substitutionTypeForIndexedAccessType2.ts]
2+
interface Foo {
3+
foo: string|undefined
4+
}
5+
6+
type Str<T extends string> = T
7+
8+
type Bar<T> =
9+
T extends Foo
10+
? T['foo'] extends string
11+
// Type 'T["foo"]' does not satisfy the constraint 'string'.
12+
// Type 'string | undefined' is not assignable to type 'string'.
13+
// Type 'undefined' is not assignable to type 'string'.(2344)
14+
? Str<T['foo']>
15+
: never
16+
: never
17+
18+
//// [substitutionTypeForIndexedAccessType2.js]
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
=== tests/cases/compiler/substitutionTypeForIndexedAccessType2.ts ===
2+
interface Foo {
3+
>Foo : Symbol(Foo, Decl(substitutionTypeForIndexedAccessType2.ts, 0, 0))
4+
5+
foo: string|undefined
6+
>foo : Symbol(Foo.foo, Decl(substitutionTypeForIndexedAccessType2.ts, 0, 15))
7+
}
8+
9+
type Str<T extends string> = T
10+
>Str : Symbol(Str, Decl(substitutionTypeForIndexedAccessType2.ts, 2, 1))
11+
>T : Symbol(T, Decl(substitutionTypeForIndexedAccessType2.ts, 4, 9))
12+
>T : Symbol(T, Decl(substitutionTypeForIndexedAccessType2.ts, 4, 9))
13+
14+
type Bar<T> =
15+
>Bar : Symbol(Bar, Decl(substitutionTypeForIndexedAccessType2.ts, 4, 30))
16+
>T : Symbol(T, Decl(substitutionTypeForIndexedAccessType2.ts, 6, 9))
17+
18+
T extends Foo
19+
>T : Symbol(T, Decl(substitutionTypeForIndexedAccessType2.ts, 6, 9))
20+
>Foo : Symbol(Foo, Decl(substitutionTypeForIndexedAccessType2.ts, 0, 0))
21+
22+
? T['foo'] extends string
23+
>T : Symbol(T, Decl(substitutionTypeForIndexedAccessType2.ts, 6, 9))
24+
25+
// Type 'T["foo"]' does not satisfy the constraint 'string'.
26+
// Type 'string | undefined' is not assignable to type 'string'.
27+
// Type 'undefined' is not assignable to type 'string'.(2344)
28+
? Str<T['foo']>
29+
>Str : Symbol(Str, Decl(substitutionTypeForIndexedAccessType2.ts, 2, 1))
30+
>T : Symbol(T, Decl(substitutionTypeForIndexedAccessType2.ts, 6, 9))
31+
32+
: never
33+
: never
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
=== tests/cases/compiler/substitutionTypeForIndexedAccessType2.ts ===
2+
interface Foo {
3+
foo: string|undefined
4+
>foo : string
5+
}
6+
7+
type Str<T extends string> = T
8+
>Str : T
9+
10+
type Bar<T> =
11+
>Bar : Bar<T>
12+
13+
T extends Foo
14+
? T['foo'] extends string
15+
// Type 'T["foo"]' does not satisfy the constraint 'string'.
16+
// Type 'string | undefined' is not assignable to type 'string'.
17+
// Type 'undefined' is not assignable to type 'string'.(2344)
18+
? Str<T['foo']>
19+
: never
20+
: never
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
type AddPropToObject<Obj extends object, Prop extends string> = Prop extends keyof Obj
2+
? Obj[Prop] extends unknown[]
3+
? [...Obj[Prop]]
4+
: never
5+
: never
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
interface Foo {
2+
foo: string|undefined
3+
}
4+
5+
type Str<T extends string> = T
6+
7+
type Bar<T> =
8+
T extends Foo
9+
? T['foo'] extends string
10+
// Type 'T["foo"]' does not satisfy the constraint 'string'.
11+
// Type 'string | undefined' is not assignable to type 'string'.
12+
// Type 'undefined' is not assignable to type 'string'.(2344)
13+
? Str<T['foo']>
14+
: never
15+
: never

0 commit comments

Comments
 (0)