Skip to content

Commit 01aaff7

Browse files
authored
Merge pull request #10009 from Microsoft/null-undefined-allowed-as-index-expressions
`Null` and `undefined` are allowed as index expressions
2 parents 9cc8b2e + e2709d8 commit 01aaff7

8 files changed

+199
-2
lines changed

src/compiler/checker.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10842,10 +10842,11 @@ namespace ts {
1084210842
}
1084310843

1084410844
// Check for compatible indexer types.
10845-
if (isTypeAnyOrAllConstituentTypesHaveKind(indexType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) {
10845+
const allowedNullableFlags = strictNullChecks ? 0 : TypeFlags.Nullable;
10846+
if (isTypeAnyOrAllConstituentTypesHaveKind(indexType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol | allowedNullableFlags)) {
1084610847

1084710848
// Try to use a number indexer.
10848-
if (isTypeAnyOrAllConstituentTypesHaveKind(indexType, TypeFlags.NumberLike) || isForInVariableForNumericPropertyNames(node.argumentExpression)) {
10849+
if (isTypeAnyOrAllConstituentTypesHaveKind(indexType, TypeFlags.NumberLike | allowedNullableFlags) || isForInVariableForNumericPropertyNames(node.argumentExpression)) {
1084910850
const numberIndexInfo = getIndexInfoOfType(objectType, IndexKind.Number);
1085010851
if (numberIndexInfo) {
1085110852
getNodeLinks(node).resolvedIndexInfo = numberIndexInfo;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//// [indexWithUndefinedAndNull.ts]
2+
interface N {
3+
[n: number]: string;
4+
}
5+
interface S {
6+
[s: string]: number;
7+
}
8+
let n: N;
9+
let s: S;
10+
let str: string = n[undefined];
11+
str = n[null];
12+
let num: number = s[undefined];
13+
num = s[null];
14+
15+
16+
//// [indexWithUndefinedAndNull.js]
17+
var n;
18+
var s;
19+
var str = n[undefined];
20+
str = n[null];
21+
var num = s[undefined];
22+
num = s[null];
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
=== tests/cases/compiler/indexWithUndefinedAndNull.ts ===
2+
interface N {
3+
>N : Symbol(N, Decl(indexWithUndefinedAndNull.ts, 0, 0))
4+
5+
[n: number]: string;
6+
>n : Symbol(n, Decl(indexWithUndefinedAndNull.ts, 1, 5))
7+
}
8+
interface S {
9+
>S : Symbol(S, Decl(indexWithUndefinedAndNull.ts, 2, 1))
10+
11+
[s: string]: number;
12+
>s : Symbol(s, Decl(indexWithUndefinedAndNull.ts, 4, 5))
13+
}
14+
let n: N;
15+
>n : Symbol(n, Decl(indexWithUndefinedAndNull.ts, 6, 3))
16+
>N : Symbol(N, Decl(indexWithUndefinedAndNull.ts, 0, 0))
17+
18+
let s: S;
19+
>s : Symbol(s, Decl(indexWithUndefinedAndNull.ts, 7, 3))
20+
>S : Symbol(S, Decl(indexWithUndefinedAndNull.ts, 2, 1))
21+
22+
let str: string = n[undefined];
23+
>str : Symbol(str, Decl(indexWithUndefinedAndNull.ts, 8, 3))
24+
>n : Symbol(n, Decl(indexWithUndefinedAndNull.ts, 6, 3))
25+
>undefined : Symbol(undefined)
26+
27+
str = n[null];
28+
>str : Symbol(str, Decl(indexWithUndefinedAndNull.ts, 8, 3))
29+
>n : Symbol(n, Decl(indexWithUndefinedAndNull.ts, 6, 3))
30+
31+
let num: number = s[undefined];
32+
>num : Symbol(num, Decl(indexWithUndefinedAndNull.ts, 10, 3))
33+
>s : Symbol(s, Decl(indexWithUndefinedAndNull.ts, 7, 3))
34+
>undefined : Symbol(undefined)
35+
36+
num = s[null];
37+
>num : Symbol(num, Decl(indexWithUndefinedAndNull.ts, 10, 3))
38+
>s : Symbol(s, Decl(indexWithUndefinedAndNull.ts, 7, 3))
39+
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
=== tests/cases/compiler/indexWithUndefinedAndNull.ts ===
2+
interface N {
3+
>N : N
4+
5+
[n: number]: string;
6+
>n : number
7+
}
8+
interface S {
9+
>S : S
10+
11+
[s: string]: number;
12+
>s : string
13+
}
14+
let n: N;
15+
>n : N
16+
>N : N
17+
18+
let s: S;
19+
>s : S
20+
>S : S
21+
22+
let str: string = n[undefined];
23+
>str : string
24+
>n[undefined] : string
25+
>n : N
26+
>undefined : undefined
27+
28+
str = n[null];
29+
>str = n[null] : string
30+
>str : string
31+
>n[null] : string
32+
>n : N
33+
>null : null
34+
35+
let num: number = s[undefined];
36+
>num : number
37+
>s[undefined] : number
38+
>s : S
39+
>undefined : undefined
40+
41+
num = s[null];
42+
>num = s[null] : number
43+
>num : number
44+
>s[null] : number
45+
>s : S
46+
>null : null
47+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
tests/cases/compiler/indexWithUndefinedAndNullStrictNullChecks.ts(9,19): error TS2454: Variable 'n' is used before being assigned.
2+
tests/cases/compiler/indexWithUndefinedAndNullStrictNullChecks.ts(9,19): error TS2342: An index expression argument must be of type 'string', 'number', 'symbol', or 'any'.
3+
tests/cases/compiler/indexWithUndefinedAndNullStrictNullChecks.ts(10,7): error TS2454: Variable 'n' is used before being assigned.
4+
tests/cases/compiler/indexWithUndefinedAndNullStrictNullChecks.ts(10,7): error TS2342: An index expression argument must be of type 'string', 'number', 'symbol', or 'any'.
5+
tests/cases/compiler/indexWithUndefinedAndNullStrictNullChecks.ts(11,19): error TS2454: Variable 's' is used before being assigned.
6+
tests/cases/compiler/indexWithUndefinedAndNullStrictNullChecks.ts(11,19): error TS2342: An index expression argument must be of type 'string', 'number', 'symbol', or 'any'.
7+
tests/cases/compiler/indexWithUndefinedAndNullStrictNullChecks.ts(12,7): error TS2454: Variable 's' is used before being assigned.
8+
tests/cases/compiler/indexWithUndefinedAndNullStrictNullChecks.ts(12,7): error TS2342: An index expression argument must be of type 'string', 'number', 'symbol', or 'any'.
9+
10+
11+
==== tests/cases/compiler/indexWithUndefinedAndNullStrictNullChecks.ts (8 errors) ====
12+
interface N {
13+
[n: number]: string;
14+
}
15+
interface S {
16+
[s: string]: number;
17+
}
18+
let n: N;
19+
let s: S;
20+
let str: string = n[undefined];
21+
~
22+
!!! error TS2454: Variable 'n' is used before being assigned.
23+
~~~~~~~~~~~~
24+
!!! error TS2342: An index expression argument must be of type 'string', 'number', 'symbol', or 'any'.
25+
str = n[null];
26+
~
27+
!!! error TS2454: Variable 'n' is used before being assigned.
28+
~~~~~~~
29+
!!! error TS2342: An index expression argument must be of type 'string', 'number', 'symbol', or 'any'.
30+
let num: number = s[undefined];
31+
~
32+
!!! error TS2454: Variable 's' is used before being assigned.
33+
~~~~~~~~~~~~
34+
!!! error TS2342: An index expression argument must be of type 'string', 'number', 'symbol', or 'any'.
35+
num = s[null];
36+
~
37+
!!! error TS2454: Variable 's' is used before being assigned.
38+
~~~~~~~
39+
!!! error TS2342: An index expression argument must be of type 'string', 'number', 'symbol', or 'any'.
40+
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//// [indexWithUndefinedAndNullStrictNullChecks.ts]
2+
interface N {
3+
[n: number]: string;
4+
}
5+
interface S {
6+
[s: string]: number;
7+
}
8+
let n: N;
9+
let s: S;
10+
let str: string = n[undefined];
11+
str = n[null];
12+
let num: number = s[undefined];
13+
num = s[null];
14+
15+
16+
//// [indexWithUndefinedAndNullStrictNullChecks.js]
17+
var n;
18+
var s;
19+
var str = n[undefined];
20+
str = n[null];
21+
var num = s[undefined];
22+
num = s[null];
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// @strictNullChecks: false
2+
interface N {
3+
[n: number]: string;
4+
}
5+
interface S {
6+
[s: string]: number;
7+
}
8+
let n: N;
9+
let s: S;
10+
let str: string = n[undefined];
11+
str = n[null];
12+
let num: number = s[undefined];
13+
num = s[null];
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// @strictNullChecks: true
2+
interface N {
3+
[n: number]: string;
4+
}
5+
interface S {
6+
[s: string]: number;
7+
}
8+
let n: N;
9+
let s: S;
10+
let str: string = n[undefined];
11+
str = n[null];
12+
let num: number = s[undefined];
13+
num = s[null];

0 commit comments

Comments
 (0)