forked from mike-works/typescript-fundamentals
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path2-function-basics.ts
100 lines (83 loc) · 2.97 KB
/
2-function-basics.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
import { HasEmail, HasPhoneNumber } from "./1-basics";
//== FUNCTIONS ==//
// (1) function arguments and return values can have type annotations
// function sendEmail(to: HasEmail): { recipient: string; body: string } {
// return {
// recipient: `${to.name} <${to.email}>`, // Mike <mike@example.com>
// body: "You're pre-qualified for a loan!"
// };
// }
// (2) or the arrow-function variant
// const sendTextMessage = (
// to: HasPhoneNumber
// ): { recipient: string; body: string } => {
// return {
// recipient: `${to.name} <${to.phone}>`,
// body: "You're pre-qualified for a loan!"
// };
// };
// (3) return types can almost always be inferred
// function getNameParts(contact: { name: string }) {
// const parts = contact.name.split(/\s/g); // split @ whitespace
// if (parts.length < 2) {
// throw new Error(`Can't calculate name parts from name "${contact.name}"`);
// }
// return {
// first: parts[0],
// middle:
// parts.length === 2
// ? undefined
// : // everything except first and last
// parts.slice(1, parts.length - 2).join(" "),
// last: parts[parts.length - 1]
// };
// }
// (4) rest params work just as you'd think. Type must be array-ish
// const sum = (...vals: number[]) => vals.reduce((sum, x) => sum + x, 0);
// console.log(sum(3, 4, 6)); // 13
// (5) we can even provide multiple function signatures
// "overload signatures"
// function contactPeople(method: "email", ...people: HasEmail[]): void;
// function contactPeople(method: "phone", ...people: HasPhoneNumber[]): void;
// "function implementation"
// function contactPeople(
// method: "email" | "phone",
// ...people: (HasEmail | HasPhoneNumber)[]
// ): void {
// if (method === "email") {
// (people as HasEmail[]).forEach(sendEmail);
// } else {
// (people as HasPhoneNumber[]).forEach(sendTextMessage);
// }
// }
// ✅ email works
// contactPeople("email", { name: "foo", email: "" });
// ✅ phone works
// contactPeople("phone", { name: "foo", phone: 12345678 });
// 🚨 mixing does not work
// contactPeople("email", { name: "foo", phone: 12345678 });
// (6) the lexical scope (this) of a function is part of its signature
// function sendMessage(
// this: HasEmail & HasPhoneNumber,
// preferredMethod: "phone" | "email"
// ) {
// if (preferredMethod === "email") {
// console.log("sendEmail");
// sendEmail(this);
// } else {
// console.log("sendTextMessage");
// sendTextMessage(this);
// }
// }
// const c = { name: "Mike", phone: 3215551212, email: "mike@example.com" };
// function invokeSoon(cb: () => any, timeout: number) {
// setTimeout(() => cb.call(null), timeout);
// }
// 🚨 this is not satisfied
// invokeSoon(() => sendMessage("email"), 500);
// ✅ creating a bound function is one solution
// const bound = sendMessage.bind(c, "email");
// invokeSoon(() => bound(), 500);
// ✅ call/apply works as well
// invokeSoon(() => sendMessage.apply(c, ["phone"]), 500);
export default {};