assertie 0.3.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -1
- package/MIGRATION-GUIDE.md +13 -0
- package/README.md +18 -6
- package/lib/assert-helpers.d.ts +20 -0
- package/lib/assert-helpers.js +66 -0
- package/lib/index.d.ts +49 -56
- package/lib/index.js +56 -117
- package/lib/types.d.ts +29 -0
- package/lib/types.js +1 -0
- package/package.json +9 -4
- package/src/assert-helpers.ts +63 -0
- package/src/index.ts +146 -143
- package/src/types.ts +39 -0
- package/test/runtime/assert-helpers.test.ts +583 -0
- package/test/runtime/asserts.test.ts +641 -0
- package/test/runtime/main.ts +6 -0
- package/test/runtime/testing.ts +168 -0
- package/test/runtime/tsconfig.json +18 -0
- package/test/types/readonly.5+.test.ts +44 -0
- package/test/types/readonly.test.ts +238 -0
- package/test/types/run.ts +29 -0
- package/test/types/tsconfig.4.x.json +7 -0
- package/test/types/tsconfig.json +18 -0
- package/test/types/type-narrowing.5+.test.ts +32 -0
- package/test/types/type-narrowing.test.ts +654 -0
- package/tsconfig.json +1 -0
|
@@ -0,0 +1,654 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assert,
|
|
3
|
+
assertType,
|
|
4
|
+
assertArrayType,
|
|
5
|
+
assertTupleTypes,
|
|
6
|
+
assertTypeOfString,
|
|
7
|
+
assertTypeOfNumber,
|
|
8
|
+
assertTypeOfBoolean,
|
|
9
|
+
assertTypeOfBigint,
|
|
10
|
+
assertTypeOfUndefined,
|
|
11
|
+
assertTypeOfFunction,
|
|
12
|
+
assertTypeOfObject,
|
|
13
|
+
assertTypeOfSymbol,
|
|
14
|
+
assertNull,
|
|
15
|
+
assertInstanceOf,
|
|
16
|
+
assertIsTuple,
|
|
17
|
+
assertUnreachable,
|
|
18
|
+
assertNonNullable,
|
|
19
|
+
assertPropsNonNullable,
|
|
20
|
+
assertArrayNonNullable,
|
|
21
|
+
assertTupleNonNullable,
|
|
22
|
+
assertFiniteNumber,
|
|
23
|
+
} from "../../src/index";
|
|
24
|
+
|
|
25
|
+
/* ==================== assert ==================== */
|
|
26
|
+
|
|
27
|
+
{ // narrows boolean to true
|
|
28
|
+
const x: boolean = true as boolean;
|
|
29
|
+
// @ts-expect-error
|
|
30
|
+
let _true: true = x;
|
|
31
|
+
assert(x);
|
|
32
|
+
_true = x;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* ==================== assertType ==================== */
|
|
36
|
+
|
|
37
|
+
{ // narrows unknown to string with string literal
|
|
38
|
+
const x: unknown = "test";
|
|
39
|
+
// @ts-expect-error
|
|
40
|
+
let _string: string = x;
|
|
41
|
+
assertType(x, "string");
|
|
42
|
+
_string = x;
|
|
43
|
+
}
|
|
44
|
+
{ // narrows unknown to number with string literal
|
|
45
|
+
const x: unknown = 42;
|
|
46
|
+
// @ts-expect-error
|
|
47
|
+
let _number: number = x;
|
|
48
|
+
assertType(x, "number");
|
|
49
|
+
_number = x;
|
|
50
|
+
}
|
|
51
|
+
{ // narrows unknown to boolean with string literal
|
|
52
|
+
const x: unknown = true;
|
|
53
|
+
// @ts-expect-error
|
|
54
|
+
let _boolean: boolean = x;
|
|
55
|
+
assertType(x, "boolean");
|
|
56
|
+
_boolean = x;
|
|
57
|
+
}
|
|
58
|
+
{ // narrows unknown to bigint with string literal
|
|
59
|
+
const x: unknown = 123n;
|
|
60
|
+
// @ts-expect-error
|
|
61
|
+
let _bigint: bigint = x;
|
|
62
|
+
assertType(x, "bigint");
|
|
63
|
+
_bigint = x;
|
|
64
|
+
}
|
|
65
|
+
{ // narrows unknown to undefined with string literal
|
|
66
|
+
const x: unknown = undefined;
|
|
67
|
+
// @ts-expect-error
|
|
68
|
+
let _undefined: undefined = x;
|
|
69
|
+
assertType(x, "undefined");
|
|
70
|
+
_undefined = x;
|
|
71
|
+
}
|
|
72
|
+
{ // narrows unknown to function with string literal
|
|
73
|
+
const x: unknown = () => {};
|
|
74
|
+
// @ts-expect-error
|
|
75
|
+
x();
|
|
76
|
+
assertType(x, "function");
|
|
77
|
+
x();
|
|
78
|
+
}
|
|
79
|
+
{ // narrows unknown to object with string literal
|
|
80
|
+
const x: unknown = {};
|
|
81
|
+
// @ts-expect-error
|
|
82
|
+
let _object: object = x;
|
|
83
|
+
assertType(x, "object");
|
|
84
|
+
_object = x;
|
|
85
|
+
}
|
|
86
|
+
{ // narrows unknown to symbol with string literal
|
|
87
|
+
const x: unknown = Symbol("test");
|
|
88
|
+
// @ts-expect-error
|
|
89
|
+
let _symbol: symbol = x;
|
|
90
|
+
assertType(x, "symbol");
|
|
91
|
+
_symbol = x;
|
|
92
|
+
}
|
|
93
|
+
{ // narrows unknown to null with null literal
|
|
94
|
+
const x: unknown = null;
|
|
95
|
+
// @ts-expect-error
|
|
96
|
+
let _null: null = x;
|
|
97
|
+
assertType(x, null);
|
|
98
|
+
_null = x;
|
|
99
|
+
}
|
|
100
|
+
{ // narrows unknown to undefined with undefined literal
|
|
101
|
+
const x: unknown = undefined;
|
|
102
|
+
// @ts-expect-error
|
|
103
|
+
let _undefined: undefined = x;
|
|
104
|
+
assertType(x, undefined);
|
|
105
|
+
_undefined = x;
|
|
106
|
+
}
|
|
107
|
+
{ // narrows unknown to class instance with constructor
|
|
108
|
+
const x: unknown = new Date();
|
|
109
|
+
// @ts-expect-error
|
|
110
|
+
let _date: Date = x;
|
|
111
|
+
assertType(x, Date);
|
|
112
|
+
_date = x;
|
|
113
|
+
}
|
|
114
|
+
{ // narrows unknown to custom class instance
|
|
115
|
+
class CustomClass {
|
|
116
|
+
constructor(_: string) {}
|
|
117
|
+
}
|
|
118
|
+
const x: unknown = new CustomClass("test");
|
|
119
|
+
// @ts-expect-error
|
|
120
|
+
let _custom: CustomClass = x;
|
|
121
|
+
assertType(x, CustomClass);
|
|
122
|
+
_custom = x;
|
|
123
|
+
}
|
|
124
|
+
{ // narrows unknown to abstract class instance
|
|
125
|
+
abstract class BaseClass {
|
|
126
|
+
abstract label: string;
|
|
127
|
+
}
|
|
128
|
+
class ConcreteClass extends BaseClass {
|
|
129
|
+
label = "ok";
|
|
130
|
+
}
|
|
131
|
+
const x: unknown = new ConcreteClass();
|
|
132
|
+
// @ts-expect-error
|
|
133
|
+
let _base: BaseClass = x;
|
|
134
|
+
assertType(x, BaseClass);
|
|
135
|
+
_base = x;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* ==================== assertArrayType ==================== */
|
|
139
|
+
|
|
140
|
+
{ // narrows unknown[] to string[]
|
|
141
|
+
const arr: unknown[] = ["a", "b"];
|
|
142
|
+
// @ts-expect-error
|
|
143
|
+
let _strings: string[] = arr;
|
|
144
|
+
assertArrayType(arr, "string");
|
|
145
|
+
_strings = arr;
|
|
146
|
+
}
|
|
147
|
+
{ // narrows unknown[] to number[]
|
|
148
|
+
const arr: unknown[] = [1, 2, 3];
|
|
149
|
+
// @ts-expect-error
|
|
150
|
+
let _numbers: number[] = arr;
|
|
151
|
+
assertArrayType(arr, "number");
|
|
152
|
+
_numbers = arr;
|
|
153
|
+
}
|
|
154
|
+
{ // narrows (string | number)[] to number[]
|
|
155
|
+
const arr: (string | number)[] = [1, 2, 3];
|
|
156
|
+
// @ts-expect-error
|
|
157
|
+
let _numbers: number[] = arr;
|
|
158
|
+
assertArrayType(arr, "number");
|
|
159
|
+
_numbers = arr;
|
|
160
|
+
}
|
|
161
|
+
{ // narrows unknown[] to Date[]
|
|
162
|
+
const arr: unknown[] = [new Date(), new Date()];
|
|
163
|
+
// @ts-expect-error
|
|
164
|
+
let _dates: Date[] = arr;
|
|
165
|
+
assertArrayType(arr, Date);
|
|
166
|
+
_dates = arr;
|
|
167
|
+
}
|
|
168
|
+
{ // narrows unknown[] to null[]
|
|
169
|
+
const arr: unknown[] = [null, null];
|
|
170
|
+
// @ts-expect-error
|
|
171
|
+
let _nulls: null[] = arr;
|
|
172
|
+
assertArrayType(arr, null);
|
|
173
|
+
_nulls = arr;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/* ==================== assertTupleTypes ==================== */
|
|
177
|
+
|
|
178
|
+
{ // narrows tuple to specific types
|
|
179
|
+
const tuple: [unknown, unknown] = [1, "a"];
|
|
180
|
+
// @ts-expect-error
|
|
181
|
+
let _tuple: [number, string] = tuple;
|
|
182
|
+
assertTupleTypes(tuple, ["number", "string"]);
|
|
183
|
+
_tuple = tuple;
|
|
184
|
+
}
|
|
185
|
+
{ // narrows array to tuple with specific types
|
|
186
|
+
const arr: unknown[] = [1, "a", true];
|
|
187
|
+
// @ts-expect-error
|
|
188
|
+
let _tuple: [number, string, boolean] = arr;
|
|
189
|
+
assertTupleTypes(arr, ["number", "string", "boolean"]);
|
|
190
|
+
_tuple = arr;
|
|
191
|
+
}
|
|
192
|
+
{ // narrows tuple with null and undefined
|
|
193
|
+
const tuple: [unknown, unknown] = [null, undefined];
|
|
194
|
+
// @ts-expect-error
|
|
195
|
+
let _tuple: [null, undefined] = tuple;
|
|
196
|
+
assertTupleTypes(tuple, [null, undefined]);
|
|
197
|
+
_tuple = tuple;
|
|
198
|
+
}
|
|
199
|
+
{ // narrows tuple with class constructor
|
|
200
|
+
const tuple: [unknown, unknown] = [new Date(), new Error()];
|
|
201
|
+
// @ts-expect-error
|
|
202
|
+
let _tuple: [Date, Error] = tuple;
|
|
203
|
+
assertTupleTypes(tuple, [Date, Error]);
|
|
204
|
+
_tuple = tuple;
|
|
205
|
+
}
|
|
206
|
+
{ // narrows mixed primitive and class tuple
|
|
207
|
+
const tuple: [unknown, unknown, unknown] = [1, "str", new Date()];
|
|
208
|
+
// @ts-expect-error
|
|
209
|
+
let _tuple: [number, string, Date] = tuple;
|
|
210
|
+
assertTupleTypes(tuple, ["number", "string", Date]);
|
|
211
|
+
_tuple = tuple;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/* ==================== assertTypeOfString ==================== */
|
|
215
|
+
|
|
216
|
+
{ // narrows unknown to string
|
|
217
|
+
const x: unknown = "test";
|
|
218
|
+
// @ts-expect-error
|
|
219
|
+
let _string: string = x;
|
|
220
|
+
assertTypeOfString(x);
|
|
221
|
+
_string = x;
|
|
222
|
+
}
|
|
223
|
+
{ // narrows union to string
|
|
224
|
+
const x: string | number = "test" as string | number;
|
|
225
|
+
// @ts-expect-error
|
|
226
|
+
let _string: string = x;
|
|
227
|
+
assertTypeOfString(x);
|
|
228
|
+
_string = x;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/* ==================== assertTypeOfNumber ==================== */
|
|
232
|
+
|
|
233
|
+
{ // narrows unknown to number
|
|
234
|
+
const x: unknown = 42;
|
|
235
|
+
// @ts-expect-error
|
|
236
|
+
let _number: number = x;
|
|
237
|
+
assertTypeOfNumber(x);
|
|
238
|
+
_number = x;
|
|
239
|
+
}
|
|
240
|
+
{ // narrows union to number
|
|
241
|
+
const x: string | number = 42 as string | number;
|
|
242
|
+
// @ts-expect-error
|
|
243
|
+
let _number: number = x;
|
|
244
|
+
assertTypeOfNumber(x);
|
|
245
|
+
_number = x;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/* ==================== assertTypeOfBoolean ==================== */
|
|
249
|
+
|
|
250
|
+
{ // narrows unknown to boolean
|
|
251
|
+
const x: unknown = true;
|
|
252
|
+
// @ts-expect-error
|
|
253
|
+
let _boolean: boolean = x;
|
|
254
|
+
assertTypeOfBoolean(x);
|
|
255
|
+
_boolean = x;
|
|
256
|
+
}
|
|
257
|
+
{ // narrows union to boolean
|
|
258
|
+
const x: string | boolean = false as string | boolean;
|
|
259
|
+
// @ts-expect-error
|
|
260
|
+
let _boolean: boolean = x;
|
|
261
|
+
assertTypeOfBoolean(x);
|
|
262
|
+
_boolean = x;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/* ==================== assertTypeOfBigint ==================== */
|
|
266
|
+
|
|
267
|
+
{ // narrows unknown to bigint
|
|
268
|
+
const x: unknown = 123n;
|
|
269
|
+
// @ts-expect-error
|
|
270
|
+
let _bigint: bigint = x;
|
|
271
|
+
assertTypeOfBigint(x);
|
|
272
|
+
_bigint = x;
|
|
273
|
+
}
|
|
274
|
+
{ // narrows union to bigint
|
|
275
|
+
const x: string | bigint = 123n as string | bigint;
|
|
276
|
+
// @ts-expect-error
|
|
277
|
+
let _bigint: bigint = x;
|
|
278
|
+
assertTypeOfBigint(x);
|
|
279
|
+
_bigint = x;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/* ==================== assertTypeOfUndefined ==================== */
|
|
283
|
+
|
|
284
|
+
{ // narrows unknown to undefined
|
|
285
|
+
const x: unknown = undefined;
|
|
286
|
+
// @ts-expect-error
|
|
287
|
+
let _undefined: undefined = x;
|
|
288
|
+
assertTypeOfUndefined(x);
|
|
289
|
+
_undefined = x;
|
|
290
|
+
}
|
|
291
|
+
{ // narrows union to undefined
|
|
292
|
+
const x: string | undefined = undefined as string | undefined;
|
|
293
|
+
// @ts-expect-error
|
|
294
|
+
let _undefined: undefined = x;
|
|
295
|
+
assertTypeOfUndefined(x);
|
|
296
|
+
_undefined = x;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/* ==================== assertTypeOfFunction ==================== */
|
|
300
|
+
|
|
301
|
+
{ // narrows unknown to function
|
|
302
|
+
const x: unknown = () => {};
|
|
303
|
+
// @ts-expect-error
|
|
304
|
+
x();
|
|
305
|
+
assertTypeOfFunction(x);
|
|
306
|
+
x();
|
|
307
|
+
// Ensure it narrows to () => unknown not () => any
|
|
308
|
+
// @ts-expect-error
|
|
309
|
+
const res: string = x();
|
|
310
|
+
}
|
|
311
|
+
{ // narrows union to function
|
|
312
|
+
type X = string | ((arg: string) => string);
|
|
313
|
+
const x: X = ((arg: string) => arg) as X;
|
|
314
|
+
// @ts-expect-error
|
|
315
|
+
x("test");
|
|
316
|
+
assertTypeOfFunction(x);
|
|
317
|
+
x("test");
|
|
318
|
+
// TypeScript 4.7.0 only narrows to () => {} or (args: any[]) => {}
|
|
319
|
+
// It would allow x(123), even though it's not a string => string,
|
|
320
|
+
// so there is a test in latest.test.ts that tests narrowing to specific function
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/* ==================== assertTypeOfObject ==================== */
|
|
324
|
+
|
|
325
|
+
{ // narrows unknown to object
|
|
326
|
+
const x: unknown = {};
|
|
327
|
+
// @ts-expect-error
|
|
328
|
+
let _object: object = x;
|
|
329
|
+
assertTypeOfObject(x);
|
|
330
|
+
_object = x;
|
|
331
|
+
}
|
|
332
|
+
{ // narrows union to specific object
|
|
333
|
+
type X = string | { a: string };
|
|
334
|
+
const x: X = { a: "test" } as X;
|
|
335
|
+
// @ts-expect-error
|
|
336
|
+
let _object: { a: string } = x;
|
|
337
|
+
// @ts-expect-error
|
|
338
|
+
let _str: string = x.a;
|
|
339
|
+
assertTypeOfObject(x);
|
|
340
|
+
_object = x;
|
|
341
|
+
_str = x.a;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/* ==================== assertTypeOfSymbol ==================== */
|
|
345
|
+
|
|
346
|
+
{ // narrows unknown to symbol
|
|
347
|
+
const x: unknown = Symbol("test");
|
|
348
|
+
// @ts-expect-error
|
|
349
|
+
let _symbol: symbol = x;
|
|
350
|
+
assertTypeOfSymbol(x);
|
|
351
|
+
_symbol = x;
|
|
352
|
+
}
|
|
353
|
+
{ // narrows union to symbol
|
|
354
|
+
const x: string | symbol = Symbol("test") as string | symbol;
|
|
355
|
+
// @ts-expect-error
|
|
356
|
+
let _symbol: symbol = x;
|
|
357
|
+
assertTypeOfSymbol(x);
|
|
358
|
+
_symbol = x;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/* ==================== assertNull ==================== */
|
|
362
|
+
|
|
363
|
+
{ // narrows unknown to null
|
|
364
|
+
const x: unknown = null;
|
|
365
|
+
// @ts-expect-error
|
|
366
|
+
let _null: null = x;
|
|
367
|
+
assertNull(x);
|
|
368
|
+
_null = x;
|
|
369
|
+
}
|
|
370
|
+
{ // narrows union to null
|
|
371
|
+
const x: string | null = null as string | null;
|
|
372
|
+
// @ts-expect-error
|
|
373
|
+
let _null: null = x;
|
|
374
|
+
assertNull(x);
|
|
375
|
+
_null = x;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/* ==================== assertInstanceOf ==================== */
|
|
379
|
+
|
|
380
|
+
{ // narrows unknown to Date
|
|
381
|
+
const x: unknown = new Date();
|
|
382
|
+
// @ts-expect-error
|
|
383
|
+
let _date: Date = x;
|
|
384
|
+
assertInstanceOf(x, Date);
|
|
385
|
+
_date = x;
|
|
386
|
+
}
|
|
387
|
+
{ // narrows unknown to Error
|
|
388
|
+
const x: unknown = new Error("test");
|
|
389
|
+
// @ts-expect-error
|
|
390
|
+
let _error: Error = x;
|
|
391
|
+
assertInstanceOf(x, Error);
|
|
392
|
+
_error = x;
|
|
393
|
+
}
|
|
394
|
+
{ // narrows unknown to custom class
|
|
395
|
+
class MyClass {
|
|
396
|
+
constructor(_: string) {}
|
|
397
|
+
}
|
|
398
|
+
const x: unknown = new MyClass("test");
|
|
399
|
+
// @ts-expect-error
|
|
400
|
+
let _myClass: MyClass = x;
|
|
401
|
+
assertInstanceOf(x, MyClass);
|
|
402
|
+
_myClass = x;
|
|
403
|
+
}
|
|
404
|
+
{ // narrows unknown to abstract base class
|
|
405
|
+
abstract class BaseClass {
|
|
406
|
+
abstract label: string;
|
|
407
|
+
}
|
|
408
|
+
class ConcreteClass extends BaseClass {
|
|
409
|
+
label = "ok";
|
|
410
|
+
}
|
|
411
|
+
const x: unknown = new ConcreteClass();
|
|
412
|
+
// @ts-expect-error
|
|
413
|
+
let _base: BaseClass = x;
|
|
414
|
+
assertInstanceOf(x, BaseClass);
|
|
415
|
+
_base = x;
|
|
416
|
+
}
|
|
417
|
+
{ // narrows Node to HTMLElement
|
|
418
|
+
const x: Node = new HTMLElement();
|
|
419
|
+
// @ts-expect-error
|
|
420
|
+
let _element: HTMLElement = x;
|
|
421
|
+
assertInstanceOf(x, HTMLElement);
|
|
422
|
+
_element = x;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/* ==================== assertIsTuple ==================== */
|
|
426
|
+
|
|
427
|
+
{ // narrows number[] array to tuple
|
|
428
|
+
const arr: number[] = [1, 2];
|
|
429
|
+
// @ts-expect-error
|
|
430
|
+
let _tuple: [number, number] = arr;
|
|
431
|
+
assertIsTuple(arr, 2);
|
|
432
|
+
_tuple = arr;
|
|
433
|
+
arr[1];
|
|
434
|
+
// @ts-expect-error
|
|
435
|
+
arr[2];
|
|
436
|
+
}
|
|
437
|
+
{ // narrows string array to tuple
|
|
438
|
+
const arr: string[] = ["a", "b", "c"];
|
|
439
|
+
// @ts-expect-error
|
|
440
|
+
let _tuple: [string, string, string] = arr;
|
|
441
|
+
assertIsTuple(arr, 3);
|
|
442
|
+
_tuple = arr;
|
|
443
|
+
arr[2];
|
|
444
|
+
// @ts-expect-error
|
|
445
|
+
arr[3];
|
|
446
|
+
}
|
|
447
|
+
{ // narrows boolean array to tuple
|
|
448
|
+
const arr: boolean[] = [true];
|
|
449
|
+
// @ts-expect-error
|
|
450
|
+
let _tuple: [boolean] = arr;
|
|
451
|
+
assertIsTuple(arr, 1);
|
|
452
|
+
_tuple = arr;
|
|
453
|
+
arr[0];
|
|
454
|
+
// @ts-expect-error
|
|
455
|
+
arr[1];
|
|
456
|
+
}
|
|
457
|
+
{ // narrows mixed array to tuple
|
|
458
|
+
const arr: (number | string)[] = [1, "a"];
|
|
459
|
+
// @ts-expect-error
|
|
460
|
+
let _tuple: [number | string, number | string] = arr;
|
|
461
|
+
assertIsTuple(arr, 2);
|
|
462
|
+
_tuple = arr;
|
|
463
|
+
arr[1];
|
|
464
|
+
// @ts-expect-error
|
|
465
|
+
arr[2];
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/* ==================== assertUnreachable ==================== */
|
|
469
|
+
|
|
470
|
+
{ // accepts never type after exhaustive switch
|
|
471
|
+
type State = "a" | "b";
|
|
472
|
+
let state: State = "a" as State;
|
|
473
|
+
|
|
474
|
+
switch (state) {
|
|
475
|
+
case "a": {
|
|
476
|
+
const _a: "a" = state;
|
|
477
|
+
break;
|
|
478
|
+
}
|
|
479
|
+
case "b": {
|
|
480
|
+
const _b: "b" = state;
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
483
|
+
default: {
|
|
484
|
+
assertUnreachable(state);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
{ // errors when switch is not exhaustive
|
|
489
|
+
type State = "a" | "b";
|
|
490
|
+
let state: State = "a" as State;
|
|
491
|
+
|
|
492
|
+
switch (state) {
|
|
493
|
+
case "a": {
|
|
494
|
+
const _a: "a" = state;
|
|
495
|
+
break;
|
|
496
|
+
}
|
|
497
|
+
default: {
|
|
498
|
+
// @ts-expect-error
|
|
499
|
+
assertUnreachable(state);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/* ==================== assertNonNullable ==================== */
|
|
505
|
+
|
|
506
|
+
{ // removes null from union
|
|
507
|
+
const x: string | null = "test" as string | null;
|
|
508
|
+
// @ts-expect-error
|
|
509
|
+
let _string: string = x;
|
|
510
|
+
assertNonNullable(x);
|
|
511
|
+
_string = x;
|
|
512
|
+
}
|
|
513
|
+
{ // removes undefined from union
|
|
514
|
+
const x: string | undefined = "test" as string | undefined;
|
|
515
|
+
// @ts-expect-error
|
|
516
|
+
let _string: string = x;
|
|
517
|
+
assertNonNullable(x);
|
|
518
|
+
_string = x;
|
|
519
|
+
}
|
|
520
|
+
{ // removes null and undefined from union
|
|
521
|
+
const x: string | null | undefined = "test" as string | null | undefined;
|
|
522
|
+
// @ts-expect-error
|
|
523
|
+
let _string: string = x;
|
|
524
|
+
assertNonNullable(x);
|
|
525
|
+
_string = x;
|
|
526
|
+
}
|
|
527
|
+
{ // resolves complex union types
|
|
528
|
+
type X = number | string | null | undefined;
|
|
529
|
+
const x: X = 42 as X;
|
|
530
|
+
// @ts-expect-error
|
|
531
|
+
let _value: number | string = x;
|
|
532
|
+
assertNonNullable(x);
|
|
533
|
+
_value = x;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/* ==================== assertPropsNonNullable ==================== */
|
|
537
|
+
|
|
538
|
+
{ // narrows optional property to required
|
|
539
|
+
const obj: { a?: string; b: number } = { a: "test", b: 1 };
|
|
540
|
+
// @ts-expect-error
|
|
541
|
+
let _a: string = obj.a;
|
|
542
|
+
assertPropsNonNullable(obj, ["a"]);
|
|
543
|
+
_a = obj.a;
|
|
544
|
+
}
|
|
545
|
+
{ // narrows nullable property to non-nullable
|
|
546
|
+
const obj: { a: string | null; b: number } = { a: "test", b: 1 };
|
|
547
|
+
// @ts-expect-error
|
|
548
|
+
let _a: string = obj.a;
|
|
549
|
+
assertPropsNonNullable(obj, ["a"]);
|
|
550
|
+
_a = obj.a;
|
|
551
|
+
}
|
|
552
|
+
{ // narrows multiple properties
|
|
553
|
+
const obj: { a?: string; b: number | null; c: boolean } = {
|
|
554
|
+
a: "test",
|
|
555
|
+
b: 1,
|
|
556
|
+
c: true,
|
|
557
|
+
};
|
|
558
|
+
// @ts-expect-error
|
|
559
|
+
let _a: string = obj.a;
|
|
560
|
+
// @ts-expect-error
|
|
561
|
+
let _b: number = obj.b;
|
|
562
|
+
assertPropsNonNullable(obj, ["a", "b"]);
|
|
563
|
+
_a = obj.a;
|
|
564
|
+
_b = obj.b;
|
|
565
|
+
const _c: boolean = obj.c;
|
|
566
|
+
}
|
|
567
|
+
{ // leaves non-asserted props with original types
|
|
568
|
+
const obj: { a?: string; b: number | null } = { a: "test", b: null };
|
|
569
|
+
// @ts-expect-error
|
|
570
|
+
let _a: string = obj.a;
|
|
571
|
+
assertPropsNonNullable(obj, ["a"]);
|
|
572
|
+
_a = obj.a;
|
|
573
|
+
// @ts-expect-error
|
|
574
|
+
const _b: number = obj.b;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/* ==================== assertArrayNonNullable ==================== */
|
|
578
|
+
|
|
579
|
+
{ // removes null from array element type
|
|
580
|
+
const arr: (string | null)[] = ["a", "b"];
|
|
581
|
+
// @ts-expect-error
|
|
582
|
+
let _strings: string[] = arr;
|
|
583
|
+
assertArrayNonNullable(arr);
|
|
584
|
+
_strings = arr;
|
|
585
|
+
}
|
|
586
|
+
{ // removes undefined from array element type
|
|
587
|
+
const arr: (string | undefined)[] = ["a", "b"];
|
|
588
|
+
// @ts-expect-error
|
|
589
|
+
let _strings: string[] = arr;
|
|
590
|
+
assertArrayNonNullable(arr);
|
|
591
|
+
_strings = arr;
|
|
592
|
+
}
|
|
593
|
+
{ // removes both null and undefined
|
|
594
|
+
const arr: (number | null | undefined)[] = [1, 2, 3];
|
|
595
|
+
// @ts-expect-error
|
|
596
|
+
let _numbers: number[] = arr;
|
|
597
|
+
assertArrayNonNullable(arr);
|
|
598
|
+
_numbers = arr;
|
|
599
|
+
}
|
|
600
|
+
{ // resolves complex union element types
|
|
601
|
+
const arr: (string | number | null | undefined)[] = [1, "a"];
|
|
602
|
+
// @ts-expect-error
|
|
603
|
+
let _nonNulls: (string | number)[] = arr;
|
|
604
|
+
assertArrayNonNullable(arr);
|
|
605
|
+
_nonNulls = arr;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/* ==================== assertTupleNonNullable ==================== */
|
|
609
|
+
|
|
610
|
+
{ // removes null from tuple element types
|
|
611
|
+
const tuple: [string | null, number | null] = ["a", 1];
|
|
612
|
+
// @ts-expect-error
|
|
613
|
+
let _tuple: [string, number] = tuple;
|
|
614
|
+
assertTupleNonNullable(tuple);
|
|
615
|
+
_tuple = tuple;
|
|
616
|
+
}
|
|
617
|
+
{ // removes undefined from tuple element types
|
|
618
|
+
const tuple: [string | undefined, number | undefined] = ["a", 1];
|
|
619
|
+
// @ts-expect-error
|
|
620
|
+
let _tuple: [string, number] = tuple;
|
|
621
|
+
assertTupleNonNullable(tuple);
|
|
622
|
+
_tuple = tuple;
|
|
623
|
+
}
|
|
624
|
+
{ // removes both null and undefined from tuple
|
|
625
|
+
const tuple: [string | null | undefined, number | null | undefined] = ["a", 1];
|
|
626
|
+
// @ts-expect-error
|
|
627
|
+
let _tuple: [string, number] = tuple;
|
|
628
|
+
assertTupleNonNullable(tuple);
|
|
629
|
+
_tuple = tuple;
|
|
630
|
+
}
|
|
631
|
+
{ // handles mixed element types in tuple
|
|
632
|
+
const tuple: [string | null, number, boolean | undefined] = ["a", 1, true];
|
|
633
|
+
// @ts-expect-error
|
|
634
|
+
let _tuple: [string, number, boolean] = tuple;
|
|
635
|
+
assertTupleNonNullable(tuple);
|
|
636
|
+
_tuple = tuple;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/* ==================== assertFiniteNumber ==================== */
|
|
640
|
+
|
|
641
|
+
{ // narrows unknown to number
|
|
642
|
+
const x: unknown = 42;
|
|
643
|
+
// @ts-expect-error
|
|
644
|
+
let _number: number = x;
|
|
645
|
+
assertFiniteNumber(x);
|
|
646
|
+
_number = x;
|
|
647
|
+
}
|
|
648
|
+
{ // narrows union to number
|
|
649
|
+
const x: string | number = 42 as string | number;
|
|
650
|
+
// @ts-expect-error
|
|
651
|
+
let _number: number = x;
|
|
652
|
+
assertFiniteNumber(x);
|
|
653
|
+
_number = x;
|
|
654
|
+
}
|