-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfinished_exercise.ts
116 lines (103 loc) · 2.35 KB
/
finished_exercise.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
// Generics simple
function loggingIdentity<T>(arg: T): T {
console.log(arg);
return arg;
}
// Generics advanced + Overloading + index types
function get<T extends object, K1 extends keyof T>(obj: T, key1: K1): T[K1];
function get<T extends object, K1 extends keyof T, K2 extends keyof T[K1]>(
obj: T,
key1: K1,
key2: K2
): T[K1][K2];
function get<
T extends object,
K1 extends keyof T,
K2 extends keyof T[K1],
K3 extends keyof T[K1][K2]
>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3];
function get(obj: { [key: string]: any }, ...path: string[]) {
return path.reduce(
(prev, next) => (prev !== undefined ? prev[next] : undefined),
obj
);
}
// Utility types
function patch<T>(obj: T, patch: Partial<T>) {
return {
...obj,
...patch
};
}
function omit<T extends object, K extends (keyof T)[]>(
obj: T,
...keys: K
): {
[K2 in Exclude<keyof T, K[number]>]: T[K2];
} {
const clone = { ...obj };
keys.forEach(key => delete clone[key]);
return clone;
}
function omit2<T extends object, K extends (keyof T)[]>(
obj: T,
...keys: K
): Omit<T, K[number]> {
const clone = { ...obj };
keys.forEach(key => delete clone[key]);
return clone;
}
// Type guards
interface Bird {
fly(): void;
}
interface Cat {
walk(): void;
}
declare function getSmallPet(): Bird | Cat;
const pet = getSmallPet();
function isBird(animal: Bird | Cat): animal is Bird {
return (animal as Bird).fly !== undefined;
}
if (isBird(pet)) {
pet.fly();
} else {
pet.walk();
}
// String/number literal types
async function animateMove(
x: number,
y: number,
easing: "EaseOut" | "EaseIn" | "EaseInOut"
): Promise<void> {}
declare function createElement(tag: "img"): HTMLImageElement;
declare function createElement(tag: "iframe"): HTMLIFrameElement;
declare function createElement(tag: string): Element;
function dndDice(type) {
return Math.ceil(Math.random() * type);
}
// Algebraic data types
interface Square {
kind: "square";
size: number;
}
interface Rectangle {
kind: "rectangle";
width: number;
height: number;
}
interface Circle {
kind: "circle";
radius: number;
}
type Shape = Square | Rectangle | Circle;
// strictNullChecks
function area(s: Shape): number {
// error: returns number | undefined
switch (s.kind) {
case "square":
return s.size * s.size;
case "rectangle":
return s.height * s.width;
}
}