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.
@@ -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
+ }
package/tsconfig.json CHANGED
@@ -6,6 +6,7 @@
6
6
  "outDir": "lib",
7
7
  "declaration": true,
8
8
  "declarationDir": "lib",
9
+ "strict": true,
9
10
  },
10
11
  "include": ["src/index.ts"],
11
12
  }