Skip to content

Commit 178f792

Browse files
authored
Merge pull request #26340 from Microsoft/neverIndexedAccess
T[K] should be 'never' when T is 'never'
2 parents 969b46e + df2af29 commit 178f792

6 files changed

+59
-1
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9149,7 +9149,7 @@ namespace ts {
91499149
}
91509150
}
91519151
if (!(indexType.flags & TypeFlags.Nullable) && isTypeAssignableToKind(indexType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbolLike)) {
9152-
if (isTypeAny(objectType)) {
9152+
if (objectType.flags & (TypeFlags.Any | TypeFlags.Never)) {
91539153
return objectType;
91549154
}
91559155
const indexInfo = isTypeAssignableToKind(indexType, TypeFlags.NumberLike) && getIndexInfoOfType(objectType, IndexKind.Number) ||

tests/baselines/reference/indexingTypesWithNever.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ declare const o3Test: ExpectType<{ a?: string; b?: number }, O3Props>;
108108
declare const o2Test: ExpectType<{ a?: string }, O2Props>;
109109
declare const o1Test: ExpectType<{}, O1Props>;
110110
declare const o0Test: ExpectType<{}, O0Props>;
111+
112+
// Repro from #23005
113+
114+
type Example<T extends Record<'a', string>> = T['a'];
115+
116+
type Res1 = Example<{ a: "x" } | { a: "y" }>; // "x" | "y"
117+
type Res2 = Example<{ a: "x" }>; // "x"
118+
type Res3 = Example<never>; // never
111119

112120

113121
//// [indexingTypesWithNever.js]

tests/baselines/reference/indexingTypesWithNever.symbols

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,3 +387,26 @@ declare const o0Test: ExpectType<{}, O0Props>;
387387
>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 54, 22))
388388
>O0Props : Symbol(O0Props, Decl(indexingTypesWithNever.ts, 102, 33))
389389

390+
// Repro from #23005
391+
392+
type Example<T extends Record<'a', string>> = T['a'];
393+
>Example : Symbol(Example, Decl(indexingTypesWithNever.ts, 108, 46))
394+
>T : Symbol(T, Decl(indexingTypesWithNever.ts, 112, 13))
395+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
396+
>T : Symbol(T, Decl(indexingTypesWithNever.ts, 112, 13))
397+
398+
type Res1 = Example<{ a: "x" } | { a: "y" }>; // "x" | "y"
399+
>Res1 : Symbol(Res1, Decl(indexingTypesWithNever.ts, 112, 53))
400+
>Example : Symbol(Example, Decl(indexingTypesWithNever.ts, 108, 46))
401+
>a : Symbol(a, Decl(indexingTypesWithNever.ts, 114, 21))
402+
>a : Symbol(a, Decl(indexingTypesWithNever.ts, 114, 34))
403+
404+
type Res2 = Example<{ a: "x" }>; // "x"
405+
>Res2 : Symbol(Res2, Decl(indexingTypesWithNever.ts, 114, 45))
406+
>Example : Symbol(Example, Decl(indexingTypesWithNever.ts, 108, 46))
407+
>a : Symbol(a, Decl(indexingTypesWithNever.ts, 115, 21))
408+
409+
type Res3 = Example<never>; // never
410+
>Res3 : Symbol(Res3, Decl(indexingTypesWithNever.ts, 115, 32))
411+
>Example : Symbol(Example, Decl(indexingTypesWithNever.ts, 108, 46))
412+

tests/baselines/reference/indexingTypesWithNever.types

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,3 +264,20 @@ declare const o1Test: ExpectType<{}, O1Props>;
264264
declare const o0Test: ExpectType<{}, O0Props>;
265265
>o0Test : "Match"
266266

267+
// Repro from #23005
268+
269+
type Example<T extends Record<'a', string>> = T['a'];
270+
>Example : T["a"]
271+
272+
type Res1 = Example<{ a: "x" } | { a: "y" }>; // "x" | "y"
273+
>Res1 : "x" | "y"
274+
>a : "x"
275+
>a : "y"
276+
277+
type Res2 = Example<{ a: "x" }>; // "x"
278+
>Res2 : "x"
279+
>a : "x"
280+
281+
type Res3 = Example<never>; // never
282+
>Res3 : never
283+

tests/baselines/reference/nonPrimitiveConstraintOfIndexAccessType.errors.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessTy
33
tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessType.ts(9,5): error TS2322: Type 'string' is not assignable to type 'T[P]'.
44
tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessType.ts(12,5): error TS2322: Type 'string' is not assignable to type 'T[P]'.
55
tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessType.ts(15,5): error TS2322: Type 'string' is not assignable to type 'T[P]'.
6+
Type 'string' is not assignable to type 'never'.
67
tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessType.ts(18,5): error TS2322: Type 'string' is not assignable to type 'T[P]'.
78
tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessType.ts(21,5): error TS2322: Type 'string' is not assignable to type 'T[P]'.
89
tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessType.ts(24,5): error TS2322: Type 'string' is not assignable to type 'T[P]'.
@@ -37,6 +38,7 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessTy
3738
tp = s;
3839
~~
3940
!!! error TS2322: Type 'string' is not assignable to type 'T[P]'.
41+
!!! error TS2322: Type 'string' is not assignable to type 'never'.
4042
}
4143
function k<T extends number, P extends keyof T>(s: string, tp: T[P]): void {
4244
tp = s;

tests/cases/compiler/indexingTypesWithNever.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,11 @@ declare const o3Test: ExpectType<{ a?: string; b?: number }, O3Props>;
109109
declare const o2Test: ExpectType<{ a?: string }, O2Props>;
110110
declare const o1Test: ExpectType<{}, O1Props>;
111111
declare const o0Test: ExpectType<{}, O0Props>;
112+
113+
// Repro from #23005
114+
115+
type Example<T extends Record<'a', string>> = T['a'];
116+
117+
type Res1 = Example<{ a: "x" } | { a: "y" }>; // "x" | "y"
118+
type Res2 = Example<{ a: "x" }>; // "x"
119+
type Res3 = Example<never>; // never

0 commit comments

Comments
 (0)