Chapters - Table of contents →
Scalars
1// 1. add types to the following variables
2// considering their usage
3
4let username
5username = 'Charly'
6username = null
7// SOLUTION:
8// let username: string // no need to add `| null`
9
10let hasSubscribed
11hasSubscribed = true
12// let hasSubscribed: boolean
13
14let zipcode
15zipcode = 75000
16zipcode = '75000'
17// SOLUTION:
18// let zipcode: string | number
19
20let distance
21distance = BigInt(9007199254740991)
22distance = undefined
23// SOLUTION:
24// let distance: bigint // no need to add `| undefined`
25
26// 2. Provide 2 solutions for `coords`
27let coords = [
28 10.23,
29 20.34,
30]
31// SOLUTIONS:
32// coords: [number, number]
33// coords: [lat: number, lng: number]
34
35
36// 3. provide multiple solutions for `position`
37let position
38position = 'left'
39position = 'top'
40position = 'right'
41position = 'bottom'
42
43// SOLUTIONS:
44// let position: 'top' | 'right' | 'bottom' | 'left' = 'top'
45// enum Position {
46// TOP = 'top'
47// RIGHT = 'right'
48// BOTTOM = 'bottom'
49// LEFT = 'left'
50// }
51// let position: Position = Position.TOP
52
53
Objects
1// 1. Build the proper `Cat` interface for the object below
2
3const cat = {
4 name: 'Meow',
5 nicknames: [
6 'mi',
7 'miaou',
8 ],
9 eats: [
10 'fish',
11 'meat',
12 'cumcumber',
13 ],
14 breed: [
15 'Mushkin',
16 'Persian',
17 ],
18 weight: 4, // in kg
19 family: {
20 id: 1,
21 name: 'Smiths',
22 },
23}
24
25// SOLUTION:
26// interface Cat {
27// name: string
28// nicknames: string[]
29// eats: ('fish' | 'meat' | 'cumcumber')[]
30// breed: ('Mushkin' | 'Persian' /* and so on ... */)[]
31// weight: number
32// family: {
33// id: number,
34// name: string
35// }
36// }
37
38// 2. on the `Cat` interface built, let's add the following
39// behaviors:
40// - a cat name should be immutable
41// - a cat might not have a family
42
43// SOLUTION:
44// interface Cat {
45// readonly name: string
46// nicknames: string[]
47// eats: ('fish' | 'meat' | 'cumcumber')[]
48// breed: ('Mushkin' | 'Persian' /* and so on ... */)[]
49// weight: number
50// family?: {
51// id: number,
52// name: string
53// }
54// }
55
56// 3. Let's now consider typing the following dog object:
57
58const dog = {
59 name: 'Dogg',
60 nicknames: [
61 'Doug',
62 'Dougy',
63 ],
64 eats: '*',
65 breed: ['Teckel'],
66 barkingLevel: 5, // backing level from 0 to 10
67 weight: 7, // in kg
68 family: {
69 id: 1,
70 name: 'Smiths',
71 },
72}
73
74// SOLUTION:
75// interface Dog {
76// name: string
77// nicknames: string[]
78// eats: ('fish' | 'meat' | 'cumcumber')[] | '*'
79// breed: ('Teckel' | 'German Shepherd' /* and so on ... */)[]
80// weight: number
81// family: {
82// id: number,
83// name: string
84// }
85// }
86
87// 4. what could we do to avoid code duplication?
88// Let's create a common `Animal` type
89
90// SOLUTION:
91// interface Family {
92// id: number,
93// name: string
94// }
95
96// interface Animal {
97// readonly name: string
98// nicknames: string[]
99// eats: ('fish' | 'meat' | 'cumcumber')[] | '*'
100// breed: ('Teckel' | 'German Shepherd' | 'Mushkin' | 'Persian' /* and so on ... */)[]
101// weight: number
102// family?: Family
103// }
104
105// interface Cat extends Animal {
106// eats: ('fish' | 'meat' | 'cumcumber')[]
107// breed: ('Mushkin' | 'Persian')[]
108// }
109
110// interface Dog extends Animal {
111// eats: ('fish' | 'meat' | 'cumcumber')[] | '*'
112// breed: ('Teckel' | 'German Shepherd')[]
113// }
114
Functions
1// 1. Type the following `formatDate()` function:
2
3function formatDate(date) {
4 return date.toLocaleString()
5}
6
7// SOLUTION:
8// function formatDate(date: Date): string {
9// return date.toLocaleString()
10// }
11
12// 2. Type the following component
13
14const Welcome = ({ firstName, lastName }) => (
15 <div>{`Hi ${firstName} ${lastName}!`}</div>
16)
17
18// SOLUTION:
19// interface WelcomeProps {
20// firstName: string
21// lastName: string
22// }
23// const Welcome = ({ firstName, lastName }: WelcomeProps) => (
24// <div>{`Hi ${firstName} ${lastName}!`}</div>
25// )
26
27function Avatar({ avatarUrl }) {
28 return <img src={avatarUrl} alt={'user avatar'} />
29}
30
31// SOLUTION:
32// function Avatar({ avatarUrl }: { avatarUrl: string }) {
33// return <img src={avatarUrl} alt={'user avatar'} />
34// }
35
36
37// 3. Type the following custom hook
38// (without looking at the training materials or VSCode higlights 😉)
39
40const useToggle = (defaultValue = false) => {
41 const [value, setValue] = useState(defaultValue)
42
43 return {
44 setToFalse: useCallback(() => {
45 setValue(false)
46 }, [setValue]),
47 setToTrue: useCallback(() => {
48 setValue(true)
49 }, [setValue]),
50 toggle: useCallback(() => {
51 setValue(!value)
52 }, [setValue, value]),
53 value,
54 }
55}
56
57// SOLUTION:
58// interface UseToggleReturnValue {
59// value: boolean
60// setToFalse: () => void
61// setToTrue: () => void
62// toggle: () => void
63// }
64//
65// const useToggle = (defaultValue = false): UseToggleReturnValue => {
66// const [value, setValue] = useState(defaultValue)
67//
68// return {
69// setToFalse: useCallback(() => {
70// setValue(false)
71// }, [setValue]),
72// setToTrue: useCallback(() => {
73// setValue(true)
74// }, [setValue]),
75// toggle: useCallback(() => {
76// setValue(!value)
77// }, [setValue, value]),
78// value,
79// }
80// }
81
82
83// 4. Provide a type definition of `useToggle()` using `interface`
84
85// SOLUTION:
86// interface UseToggle {
87//
88// (defaultValue?: boolean): {
89// value: boolean
90// setToFalse: () => void
91// setToTrue: () => void
92// toggle: () => void
93// }
94// }
95
96// 5. Type the following component by looking at its props usage
97// (ignore the <PlanSelector> error)
98
99const SignUpButton = ({
100 user: { firstName },
101 selectedPlan: initialSelectedPlan,
102 onContinue,
103}) => {
104 const [selectedPlan, setSelectedPlan] = useState(initialSelectedPlan)
105 const resetPlan = useCallback(() => {
106 setSelectedPlan(undefined)
107 }, [setSelectedPlan])
108 return (
109 <div>
110 <div></div>
111 <div>
112 {selectedPlan ? (
113 <div>
114 <div>You've choose the "{selectedPlan}" plan</div>
115 <div>
116 <button onClick={resetPlan}>Change plan</button>
117 </div>
118 </div>
119 ) : (
120 <PlanSelector onSelect={setSelectedPlan} />
121 )}
122 </div>
123 <div>
124 <button onClick={onContinue}>Continue</button>
125 </div>
126 </div>
127 )
128}
129
130// SOLUTION:
131// interface SignUpButtonProps {
132// user: {
133// firstName: string
134// }
135// selectedPlan?: string
136// onContinue: () => void
137// }
138
139// 6. on the following `Animal` type,
140// let's add a `eat()` function that takes an aliment type as unique argument
141// and return if the animal is willing to eat
142
143interface Family {
144 id: number
145 name: string
146}
147
148interface Animal {
149 readonly name: string
150 nicknames: string[]
151 eats: ('fish' | 'meat' | 'cumcumber')[] | '*'
152 breed: (
153 | 'Teckel'
154 | 'German Shepherd'
155 | 'Mushkin'
156 | 'Persian' /* and so on ... */
157 )[]
158 weight: number
159 family?: Family
160}
161
162// SOLUTION:
163// interface Animal {
164// readonly name: string
165// nicknames: string[]
166// eats: ('fish' | 'meat' | 'cumcumber')[] | '*'
167// breed: (
168// | 'Teckel'
169// | 'German Shepherd'
170// | 'Mushkin'
171// | 'Persian' /* and so on ... */
172// )[]
173// weight: number
174// family?: Family
175// eat: (food: ('fish' | 'meat' | 'cumcumber')) => boolean
176// }
177
178// 7. Let's type the following function
179// Hint: for this example, we only deal with array of `number`
180// `iterator` function is expected to return `number[]`
181
182function arrayMap(iterator) {
183 return (array: number[]) => array.map(iterator)
184}
185
186const plusOne = arrayMap((item) => item + 1)
187
188console.log(plusOne([1, 2, 3])) // => [2, 3, 4]
189
190// SOLUTION:
191// function arrayMap(iterator: (arr: number) => number[]) {
192// return (array: number[]) => array.map(iterator)
193// }
194
Problems
1// what's wrong with this example?
2// make a change to remove the error
3const myVar = 'string'
4
5if (myVar === 'Charly') {
6 console.log(
7 'hi Charly!'
8 )
9}
10
11// SOLUTION:
12// const myVar: string = 'string'
13
14// if (myVar === 'Charly') {
15// console.log(
16// 'hi Charly!'
17// )
18// }
19
20// what's wrong with this example?
21// make a change to remove the error
22interface Animal {
23 name: string
24}
25
26const animal: Animal = {
27 name: null,
28 age: 10,
29}
30
31// SOLUTION:
32// interface Animal {
33// name: string
34// age: number
35// }
36
37// const animal: Animal = {
38// name: null,
39// age: 10,
40// }
41
42
43// what's wrong with this example?
44// make a change to remove the error
45
46interface Family {
47 id: number
48 name: string
49}
50
51interface DomesticAnimal {
52 readonly name: string
53 nicknames: string[]
54 eats:
55 | (
56 | 'fish'
57 | 'meat'
58 | 'cumcumber'
59 )[]
60 | '*'
61 breed: (
62 | 'Teckel'
63 | 'German Shepherd'
64 | 'Mushkin'
65 | 'Persian' /* and so on ... */
66 )[]
67 weight: number
68 family?: Family
69}
70
71interface Cat
72 extends DomesticAnimal {
73 name: number
74 breed: (
75 | 'Mushkin'
76 | 'Persian'
77 )[]
78}
79
80// SOLUTION:
81// interface Cat
82// extends DomesticAnimal {
83// name: string
84// breed: (
85// | 'Mushkin'
86// | 'Persian'
87// )[]
88// }
89
90
91
92
93// what's wrong with this example?
94// make a change to remove the error
95
96const MyComponent = (
97 prop1: string,
98 prop2: string,
99 props3: string
100) => {
101 // ...
102 return <div />
103}
104
105;<MyComponent
106 prop1={''}
107/>
108
109
110// SOLUTION:
111// const MyComponent = (
112// { prop1, prop2, prop3 }: { prop1: string, prop2: string, prop3: string }
113// ) => {
114// // ...
115// return <div />
116// }
117
118// ;<MyComponent
119// prop1={''}
120// prop2={''}
121// prop3={''}
122// />
123
124
125// what's wrong with this example?
126// make a change to remove the error
127
128interface MyFunction {
129 (arg: number) => {
130 returnProp: string
131 returnFunc: () : void
132 }
133}
134
135// SOLUTION:
136// interface MyFunction {
137// (arg: number) : {
138// returnProp: string
139// returnFunc: () => void
140// }
141// }
142
143
144// what's wrong with this example?
145// make a change to remove the error
146
147const testFunction = (array: string[], callback: (): boolean): boolean => {
148 return callback(array)
149}
150
151// SOLUTION:
152// const testFunction = (array: string[], callback: (arr: string[]) => boolean): boolean => {
153// return callback(array)
154// }
155
156// what's wrong with this example?
157function Avatar({ user: { firstname: boolean, lastName: boolean } }) {
158 return <div />
159}
160
161// SOLUTION:
162// function Avatar({ user: { firstname, lastName } }: { user: { firstname: boolean, lastName: boolean } }) {
163// return <div />
164// }
165