• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// @strict: true
2
3type isUnknown<T> = unknown extends T ? true : false;
4type isTrue<T extends true> = T;
5
6type SomeResponse = 'yes' | 'no' | 'idk';
7let validate: (x: unknown) => SomeResponse = x => (x === 'yes' || x === 'no') ? x : 'idk'; // No error
8
9const u: unknown = undefined;
10
11declare const symb: unique symbol;
12declare const symbNonUnique: symbol;
13
14if (u === 5) {
15    const y = u.toString(10);
16}
17
18if (u === true || u === false) {
19    const someBool: boolean = u;
20}
21
22if (u === undefined) {
23    const undef: undefined = u;
24}
25
26if (u === null) {
27    const someNull: null = u;
28}
29
30if (u === symb) {
31    const symbolAlias: typeof symb = u;
32}
33
34if (!(u === 42)) {
35    type A = isTrue<isUnknown<typeof u>>
36}
37
38if (u !== 42) {
39    type B = isTrue<isUnknown<typeof u>>
40}
41
42if (u == 42) {
43    type C = isTrue<isUnknown<typeof u>>
44}
45
46if (u == true) {
47    type D = isTrue<isUnknown<typeof u>>
48}
49
50if (u == Object) {
51    type E = isTrue<isUnknown<typeof u>>
52}
53
54declare const aString: string;
55declare const aBoolean: boolean;
56declare const aNumber: number;
57declare const anObject: object;
58declare const anObjectLiteral: { x: number };
59declare const aUnion: { x: number } | { y: string };
60declare const anIntersection: { x: number } & { y: string };
61declare const aFunction: () => number;
62
63if (u === aString) {
64    let uString: string = u;
65}
66
67if (u === aBoolean) {
68    let uString: boolean = u;
69}
70
71if (u === aNumber) {
72    let uNumber: number = u;
73}
74
75if (u === anObject) {
76    let uObject: object = u;
77}
78
79if (u === anObjectLiteral) {
80    let uObjectLiteral: object = u;
81}
82
83if (u === aUnion) {
84    type unionDoesNotNarrow = isTrue<isUnknown<typeof u>>
85}
86
87if (u === anIntersection) {
88    type intersectionDoesNotNarrow = isTrue<isUnknown<typeof u>>
89}
90
91if (u === aFunction) {
92    let uFunction: object = u;
93}
94
95enum NumberEnum {
96    A,
97    B,
98    C
99}
100
101enum StringEnum {
102    A = "A",
103    B = "B",
104    C = "C"
105}
106
107if (u === NumberEnum || u === StringEnum) {
108    let enumObj: object = u;
109}
110
111if (u === NumberEnum.A) {
112    let a: NumberEnum.A = u
113}
114
115if (u === StringEnum.B) {
116    let b: StringEnum.B = u
117}
118
119function switchTestEnum(x: unknown) {
120    switch (x) {
121        case StringEnum.A:
122            const a: StringEnum.A = x;
123            break;
124        case StringEnum.B:
125            const b: StringEnum.B = x;
126            break;
127        case StringEnum.C:
128            const c: StringEnum.C = x;
129            break;
130    }
131    type End = isTrue<isUnknown<typeof x>>
132}
133
134function switchTestCollectEnum(x: unknown) {
135    switch (x) {
136        case StringEnum.A:
137            const a: StringEnum.A = x;
138        case StringEnum.B:
139            const b: StringEnum.A | StringEnum.B = x;
140        case StringEnum.C:
141            const c: StringEnum.A | StringEnum.B | StringEnum.C = x;
142            const all: StringEnum = x;
143            return;
144    }
145    type End = isTrue<isUnknown<typeof x>>
146}
147
148function switchTestLiterals(x: unknown) {
149    switch (x) {
150        case 1:
151            const one: 1 = x;
152            break;
153        case 2:
154            const two: 2 = x;
155            break;
156        case 3:
157            const three: 3 = x;
158            break;
159        case true:
160            const t: true = x;
161            break;
162        case false:
163            const f: false = x;
164            break;
165        case "A":
166            const a: "A" = x;
167            break;
168        case undefined:
169            const undef: undefined = x;
170            break;
171        case null:
172            const llun: null = x;
173            break;
174        case symb:
175            const anotherSymbol: typeof symb = x;
176            break;
177        case symbNonUnique:
178            const nonUniqueSymbol: symbol = x;
179            break;
180    }
181    type End = isTrue<isUnknown<typeof x>>
182}
183
184function switchTestObjects(x: unknown, y: () => void, z: { prop: number }) {
185    switch (x) {
186        case true:
187        case false:
188            const bool: boolean = x;
189            break;
190        case y:
191            const obj1: object = x;
192            break;
193        case z:
194            const obj2: object = x;
195            break;
196    }
197    type End = isTrue<isUnknown<typeof x>>
198}
199
200function switchResponse(x: unknown): SomeResponse {
201    switch (x) {
202        case 'yes':
203        case 'no':
204        case 'idk':
205            return x;
206        default:
207            throw new Error('unknown response');
208    }
209    // Arguably this should be never.
210    type End = isTrue<isUnknown<typeof x>>
211}
212
213function switchResponseWrong(x: unknown): SomeResponse {
214    switch (x) {
215        case 'yes':
216        case 'no':
217        case 'maybe':
218            return x; // error
219        default:
220            throw new Error('Can you repeat the question?');
221    }
222    // Arguably this should be never.
223    type End = isTrue<isUnknown<typeof x>>
224}
225
226// Repro from #33483
227
228function f2(x: unknown): string | undefined {
229  if (x !== undefined && typeof x !== 'string') {
230    throw new Error();
231  }
232  return x;
233}
234
235function notNotEquals(u: unknown)  {
236    if (u !== NumberEnum) { }
237    else {
238        const o: object = u;
239    }
240
241    if (u !== NumberEnum.A) { }
242    else {
243        const a: NumberEnum.A = u;
244    }
245
246
247    if (u !== NumberEnum.A && u !== NumberEnum.B && u !== StringEnum.A) { }
248    else {
249        const aOrB: NumberEnum.A | NumberEnum.B | StringEnum.A  = u;
250    }
251
252    // equivalent to
253    if (!(u === NumberEnum.A || u === NumberEnum.B || u === StringEnum.A)) { }
254    else {
255        const aOrB: NumberEnum.A | NumberEnum.B | StringEnum.A  = u;
256    }
257}
258
259
260
261
262