Skip to content

Commit 363d914

Browse files
authored
Merge pull request microsoft#13791 from Microsoft/typeof-string-literal-union-type
`typeof x` now has a string literal union type
2 parents a7728f8 + bcd1ef8 commit 363d914

File tree

86 files changed

+560
-741
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+560
-741
lines changed

src/compiler/checker.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,6 @@ namespace ts {
326326
"object": TypeFacts.TypeofEQObject,
327327
"function": TypeFacts.TypeofEQFunction
328328
});
329-
330329
const typeofNEFacts = createMapFromTemplate({
331330
"string": TypeFacts.TypeofNEString,
332331
"number": TypeFacts.TypeofNENumber,
@@ -336,14 +335,14 @@ namespace ts {
336335
"object": TypeFacts.TypeofNEObject,
337336
"function": TypeFacts.TypeofNEFunction
338337
});
339-
340338
const typeofTypesByName = createMapFromTemplate<Type>({
341339
"string": stringType,
342340
"number": numberType,
343341
"boolean": booleanType,
344342
"symbol": esSymbolType,
345343
"undefined": undefinedType
346344
});
345+
const typeofType = createTypeofType();
347346

348347
let jsxElementType: Type;
349348
let _jsxNamespace: string;
@@ -1727,6 +1726,10 @@ namespace ts {
17271726
return type;
17281727
}
17291728

1729+
function createTypeofType() {
1730+
return getUnionType(convertToArray(typeofEQFacts.keys(), s => getLiteralTypeForText(TypeFlags.StringLiteral, s)));
1731+
}
1732+
17301733
// A reserved member name starts with two underscores, but the third character cannot be an underscore
17311734
// or the @ symbol. A third underscore indicates an escaped form of an identifer that started
17321735
// with at least two underscores. The @ character indicates that the name is denoted by a well known ES
@@ -14626,7 +14629,7 @@ namespace ts {
1462614629

1462714630
function checkTypeOfExpression(node: TypeOfExpression): Type {
1462814631
checkExpression(node.expression);
14629-
return stringType;
14632+
return typeofType;
1463014633
}
1463114634

1463214635
function checkVoidExpression(node: VoidExpression): Type {

src/compiler/core.ts

+8
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,14 @@ namespace ts {
895895
return result;
896896
}
897897

898+
export function convertToArray<T, U>(iterator: Iterator<T>, f: (value: T) => U) {
899+
const result: U[] = [];
900+
for (let { value, done } = iterator.next(); !done; { value, done } = iterator.next()) {
901+
result.push(f(value));
902+
}
903+
return result;
904+
}
905+
898906
/**
899907
* Calls `callback` for each entry in the map, returning the first truthy result.
900908
* Use `map.forEach` instead for normal iteration.

tests/baselines/reference/TypeGuardWithEnumUnion.types

+4-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ function f1(x: Color | string) {
1212

1313
if (typeof x === "number") {
1414
>typeof x === "number" : boolean
15-
>typeof x : string
15+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
1616
>x : string | Color
1717
>"number" : "number"
1818

@@ -41,7 +41,7 @@ function f2(x: Color | string | string[]) {
4141

4242
if (typeof x === "object") {
4343
>typeof x === "object" : boolean
44-
>typeof x : string
44+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
4545
>x : string | Color | string[]
4646
>"object" : "object"
4747

@@ -54,7 +54,7 @@ function f2(x: Color | string | string[]) {
5454
}
5555
if (typeof x === "number") {
5656
>typeof x === "number" : boolean
57-
>typeof x : string
57+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
5858
>x : string | Color | string[]
5959
>"number" : "number"
6060

@@ -76,7 +76,7 @@ function f2(x: Color | string | string[]) {
7676
}
7777
if (typeof x === "string") {
7878
>typeof x === "string" : boolean
79-
>typeof x : string
79+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
8080
>x : string | Color | string[]
8181
>"string" : "string"
8282

tests/baselines/reference/anonymousClassExpression1.types

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ function f() {
44

55
return typeof class {} === "function";
66
>typeof class {} === "function" : boolean
7-
>typeof class {} : string
7+
>typeof class {} : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
88
>class {} : typeof (Anonymous class)
99
>"function" : "function"
1010
}

tests/baselines/reference/callSignatureWithoutReturnTypeAnnotationInference.types

+5-5
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,17 @@ var r6 = foo6(1);
103103
>1 : 1
104104

105105
function foo7(x) {
106-
>foo7 : (x: any) => string
106+
>foo7 : (x: any) => "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
107107
>x : any
108108

109109
return typeof x;
110-
>typeof x : string
110+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
111111
>x : any
112112
}
113113
var r7 = foo7(1);
114-
>r7 : string
115-
>foo7(1) : string
116-
>foo7 : (x: any) => string
114+
>r7 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
115+
>foo7(1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
116+
>foo7 : (x: any) => "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
117117
>1 : 1
118118

119119
// object types

tests/baselines/reference/castExpressionParentheses.types

+1-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ declare var A;
182182
>(<any>typeof A).x : any
183183
>(<any>typeof A) : any
184184
><any>typeof A : any
185-
>typeof A : string
185+
>typeof A : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
186186
>A : any
187187
>x : any
188188

tests/baselines/reference/castOfAwait.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ async function f() {
88
>0 : 0
99

1010
typeof await 0;
11-
>typeof await 0 : string
11+
>typeof await 0 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
1212
>await 0 : 0
1313
>0 : 0
1414

@@ -21,7 +21,7 @@ async function f() {
2121
>await void <string> typeof <number> void await 0 : any
2222
>void <string> typeof <number> void await 0 : undefined
2323
><string> typeof <number> void await 0 : string
24-
>typeof <number> void await 0 : string
24+
>typeof <number> void await 0 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
2525
><number> void await 0 : number
2626
>void await 0 : undefined
2727
>await 0 : 0

tests/baselines/reference/classDoesNotDependOnBaseTypes.types

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ var x: StringTree;
55

66
if (typeof x !== "string") {
77
>typeof x !== "string" : boolean
8-
>typeof x : string
8+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
99
>x : StringTree
1010
>"string" : "string"
1111

tests/baselines/reference/conditionalOperatorConditionIsBooleanType.types

+3-3
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ true ? exprString1 : exprBoolean1; // union
120120
typeof "123" == "string" ? exprBoolean1 : exprBoolean2;
121121
>typeof "123" == "string" ? exprBoolean1 : exprBoolean2 : boolean
122122
>typeof "123" == "string" : boolean
123-
>typeof "123" : string
123+
>typeof "123" : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
124124
>"123" : "123"
125125
>"string" : "string"
126126
>exprBoolean1 : boolean
@@ -262,7 +262,7 @@ var resultIsBoolean3 = typeof "123" == "string" ? exprBoolean1 : exprBoolean2;
262262
>resultIsBoolean3 : boolean
263263
>typeof "123" == "string" ? exprBoolean1 : exprBoolean2 : boolean
264264
>typeof "123" == "string" : boolean
265-
>typeof "123" : string
265+
>typeof "123" : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
266266
>"123" : "123"
267267
>"string" : "string"
268268
>exprBoolean1 : boolean
@@ -299,7 +299,7 @@ var resultIsStringOrBoolean4 = typeof "123" === "string" ? exprString1 : exprBoo
299299
>resultIsStringOrBoolean4 : string | boolean
300300
>typeof "123" === "string" ? exprString1 : exprBoolean1 : string | boolean
301301
>typeof "123" === "string" : boolean
302-
>typeof "123" : string
302+
>typeof "123" : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
303303
>"123" : "123"
304304
>"string" : "string"
305305
>exprString1 : string

tests/baselines/reference/conditionalOperatorConditoinIsStringType.types

+3-3
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ var array = ["1", "2", "3"];
123123

124124
typeof condString ? exprAny1 : exprAny2;
125125
>typeof condString ? exprAny1 : exprAny2 : any
126-
>typeof condString : string
126+
>typeof condString : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
127127
>condString : string
128128
>exprAny1 : any
129129
>exprAny2 : any
@@ -254,7 +254,7 @@ var resultIsStringOrBoolean2 = "hello" ? exprString1 : exprBoolean1; // union
254254
var resultIsAny3 = typeof condString ? exprAny1 : exprAny2;
255255
>resultIsAny3 : any
256256
>typeof condString ? exprAny1 : exprAny2 : any
257-
>typeof condString : string
257+
>typeof condString : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
258258
>condString : string
259259
>exprAny1 : any
260260
>exprAny2 : any
@@ -297,7 +297,7 @@ var resultIsObject3 = array[1] ? exprIsObject1 : exprIsObject2;
297297
var resultIsStringOrBoolean3 = typeof condString ? exprString1 : exprBoolean1; // union
298298
>resultIsStringOrBoolean3 : string | boolean
299299
>typeof condString ? exprString1 : exprBoolean1 : string | boolean
300-
>typeof condString : string
300+
>typeof condString : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
301301
>condString : string
302302
>exprString1 : string
303303
>exprBoolean1 : boolean

tests/baselines/reference/constLocalsInFunctionExpressions.types

+5-5
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ function f1() {
1212

1313
if (typeof x === "string") {
1414
>typeof x === "string" : boolean
15-
>typeof x : string
15+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
1616
>x : string | number
1717
>"string" : "string"
1818

@@ -35,7 +35,7 @@ function f2() {
3535

3636
if (typeof x !== "string") {
3737
>typeof x !== "string" : boolean
38-
>typeof x : string
38+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
3939
>x : string | number
4040
>"string" : "string"
4141

@@ -59,7 +59,7 @@ function f3() {
5959

6060
if (typeof x === "string") {
6161
>typeof x === "string" : boolean
62-
>typeof x : string
62+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
6363
>x : string | number
6464
>"string" : "string"
6565

@@ -82,7 +82,7 @@ function f4() {
8282

8383
if (typeof x !== "string") {
8484
>typeof x !== "string" : boolean
85-
>typeof x : string
85+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
8686
>x : string | number
8787
>"string" : "string"
8888

@@ -106,7 +106,7 @@ function f5() {
106106

107107
if (typeof x === "string") {
108108
>typeof x === "string" : boolean
109-
>typeof x : string
109+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
110110
>x : string | number
111111
>"string" : "string"
112112

tests/baselines/reference/controlFlowCommaOperator.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ function f(x: string | number | boolean) {
1717
>y : string | number | boolean
1818
>"" : ""
1919
>typeof x === "string" : boolean
20-
>typeof x : string
20+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
2121
>x : string | number | boolean
2222
>"string" : "string"
2323

@@ -36,7 +36,7 @@ function f(x: string | number | boolean) {
3636
>z : string | number | boolean
3737
>1 : 1
3838
>typeof x === "number" : boolean
39-
>typeof x : string
39+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
4040
>x : number | boolean
4141
>"number" : "number"
4242

tests/baselines/reference/controlFlowDoWhileStatement.types

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ function c() {
6666

6767
if (typeof x === "string") continue;
6868
>typeof x === "string" : boolean
69-
>typeof x : string
69+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
7070
>x : string | number
7171
>"string" : "string"
7272

tests/baselines/reference/controlFlowForStatement.types

+4-4
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ function d() {
8282
>x : string | number | boolean
8383
>"" : ""
8484
>typeof x === "string" : boolean
85-
>typeof x : string
85+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
8686
>x : string | number
8787
>"string" : "string"
8888
>x = 5 : 5
@@ -107,7 +107,7 @@ function e() {
107107
>"" : ""
108108
>0 : 0
109109
>typeof x !== "string" : boolean
110-
>typeof x : string
110+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
111111
>x : number | true
112112
>"string" : "string"
113113
>x = "" || true : true
@@ -128,7 +128,7 @@ function f() {
128128

129129
for (; typeof x !== "string";) {
130130
>typeof x !== "string" : boolean
131-
>typeof x : string
131+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
132132
>x : string | number | boolean
133133
>"string" : "string"
134134

@@ -137,7 +137,7 @@ function f() {
137137

138138
if (typeof x === "number") break;
139139
>typeof x === "number" : boolean
140-
>typeof x : string
140+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
141141
>x : number | boolean
142142
>"number" : "number"
143143

tests/baselines/reference/controlFlowIIFE.types

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function f1() {
1313

1414
if (typeof x === "string") {
1515
>typeof x === "string" : boolean
16-
>typeof x : string
16+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
1717
>x : string | number
1818
>"string" : "string"
1919

@@ -41,7 +41,7 @@ function f2() {
4141

4242
if (typeof x === "string") {
4343
>typeof x === "string" : boolean
44-
>typeof x : string
44+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
4545
>x : string | number
4646
>"string" : "string"
4747

@@ -73,7 +73,7 @@ function f3() {
7373

7474
if (typeof x === "string") {
7575
>typeof x === "string" : boolean
76-
>typeof x : string
76+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
7777
>x : string | number
7878
>"string" : "string"
7979

tests/baselines/reference/controlFlowIfStatement.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ function c<T>(data: string | T): T {
100100

101101
if (typeof data === 'string') {
102102
>typeof data === 'string' : boolean
103-
>typeof data : string
103+
>typeof data : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
104104
>data : string | T
105105
>'string' : "string"
106106

@@ -124,7 +124,7 @@ function d<T extends string>(data: string | T): never {
124124

125125
if (typeof data === 'string') {
126126
>typeof data === 'string' : boolean
127-
>typeof data : string
127+
>typeof data : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
128128
>data : string | T
129129
>'string' : "string"
130130

tests/baselines/reference/controlFlowWhileStatement.types

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ function c() {
6969

7070
if (typeof x === "string") continue;
7171
>typeof x === "string" : boolean
72-
>typeof x : string
72+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
7373
>x : string | number
7474
>"string" : "string"
7575

tests/baselines/reference/controlFlowWithIncompleteTypes.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function foo1() {
1616

1717
if (typeof x === "string") {
1818
>typeof x === "string" : boolean
19-
>typeof x : string
19+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
2020
>x : string | number
2121
>"string" : "string"
2222

@@ -49,7 +49,7 @@ function foo2() {
4949

5050
if (typeof x === "number") {
5151
>typeof x === "number" : boolean
52-
>typeof x : string
52+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
5353
>x : string | number
5454
>"number" : "number"
5555

0 commit comments

Comments
 (0)