-
Notifications
You must be signed in to change notification settings - Fork 0
/
4.0.spec.ts
154 lines (135 loc) · 4.38 KB
/
4.0.spec.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
describe('4.0', (): void => {
describe('Variadic Tuple Types', (): void => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function tail<T extends any[]>(arr: readonly [any, ...T]): readonly T[] {
const [, ...rest] = arr;
return rest;
}
it('spreads in tuple types can be generic', (): void => {
const myTuple = [1, 2, 3, 4] as const;
const myArray = ['hello', 'world'];
const r1 = tail(myTuple);
expect(r1).toEqual([2, 3, 4]);
const r2 = tail([...myTuple, ...myArray] as const);
expect(r2).toEqual([2, 3, 4, 'hello', 'world']);
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Arr = readonly any[];
function concat<T extends Arr, U extends Arr>(
arr1: T,
arr2: U
): [...T, ...U] {
return [...arr1, ...arr2];
}
it('rest elements can be placed anywhere in a tuple or array', (): void => {
const ary1 = [1, 2, 3];
const ary2 = ['hello', 'world'];
const result = concat(ary1, ary2);
expect(result).toEqual([1, 2, 3, 'hello', 'world']);
});
type Ary = readonly unknown[];
function partialCall<T extends Ary, U extends Ary, R>(
f: (...args: [...T, ...U]) => R,
...headArgs: T
): (...tailArgs: U) => R {
return (...tailArgs: U): R => f(...headArgs, ...tailArgs);
}
const foo = (
x: string,
y: number,
z: boolean
): { x: string; y: number; z: boolean } => ({
x,
y,
z,
});
it('inference works to enforce param in partially applied fns', (): void => {
// @ts-expect-error expects 3 args
partialCall(foo, 'hello', 100, true, 'oops');
const f3 = partialCall(foo, 'hello');
// @ts-expect-error must pass required params for the partially applied fn
f3();
const result = f3(10, true);
expect(result).toEqual({ x: 'hello', y: 10, z: true });
});
});
describe('Labeled Tuple Elements', (): void => {
type Range = [start: number, end: number];
function totalRange(...range: Range): [total: number, range: Range] {
const [start, end] = range;
const total = end - start;
return [total, range];
}
it('allows labeling tuples for better communication of intent', (): void => {
const [total] = totalRange(0, 10);
expect(total).toBe(10);
});
type Name =
| [first: string, last: string]
| [first: string, middle: string, last: string];
interface Person {
name: Name;
age: number;
}
function createPerson(name: Name, age: number): Person {
return {
name,
age,
};
}
it('supports overloads in a type safe way', (): void => {
const person = createPerson(['Homer', 'Simpson'], 45);
expect(person.name).toEqual(['Homer', 'Simpson']);
expect(person.age).toBe(45);
const personWithMiddleName = createPerson(['Homer', 'J', 'Simpson'], 45);
expect(personWithMiddleName.name).toEqual(['Homer', 'J', 'Simpson']);
});
});
describe('Class Property Inference from Constructors', (): void => {
class Square {
sideLength;
constructor(sideLength: number) {
this.sideLength = sideLength;
}
get area(): number {
return this.sideLength ** 2;
}
}
it('infers property types from constructor', (): void => {
const square = new Square(5);
expect(square.area).toBe(25);
});
});
describe('Short-Circuiting Assignment Operators', (): void => {
it('adds assignments operator to logical operations', (): void => {
let a = false;
const b = true;
// previous way
if (!a) {
a = b;
}
expect(a).toBe(true);
a = false;
a ||= b;
expect(a).toBe(true);
});
});
describe('unknown on catch Clause Bindings to replace any', (): void => {
// may be opt-in behavior in the future for non-typed catch variable
it('unknown should force type checking', (): void => {
try {
throw 'something';
} catch (e: unknown) {
// @ts-expect-error Can't access values on unknowns
console.log(e.toUpperCase());
// Object is of type 'unknown'.
if (typeof e === 'string') {
// We've narrowed 'e' down to the type 'string'.
expect(e).toBe('something');
return;
}
fail('should be a string');
}
});
});
});