-
Notifications
You must be signed in to change notification settings - Fork 0
/
01-typescript-intro.nnb
151 lines (151 loc) · 9.76 KB
/
01-typescript-intro.nnb
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
{
"cells": [
{
"language": "markdown",
"source": [
"# TypeScript\n\nEens zien hoe ChatGPT TypeScript omschrijft:\n\n![](./img/typescript-chatgpt.png)\n\nTypeScript is basically JavaScript met types. Het is een superset van JavaScript, wat betekent dat alle JavaScript code ook TypeScript code is. Omgekeerd is dit niet het geval! TypeScript is een programmeertaal die wordt omgezet (niet gecompileerd) naar JavaScript.\n\nOnderstaande functie is dus perfect geldige TypeScript code:\n\n```typescript\nfunction add(a, b) {\n return a + b;\n}\n```\n\nTypes geef je aan door na de naam van de variabele een dubbele punt te zetten, gevolgd door de naam van het type. Hetzelfde geldt voor het type van de returnwaarde van een functie.\n\nMet types wordt dit dus:\n\n```typescript\nfunction add(a: number, b: number): number {\n return a + b;\n}\n```"
],
"outputs": []
},
{
"language": "markdown",
"source": [
"## Types\n\nTypeScript kent een aantal basistypes:\n\n* `number`\n* `string`\n* `boolean`\n* `null`\n* `undefined`\n* ...\n\nMet enkel speciale:\n\n* `void`: geeft niets terug (`null` of `undefined` zijn dan wel weer mogelijk)\n* `any`: eender welke waarde, van eender welk type (niet aanbevolen)\n* `never`: geeft nooit iets terug\n * bij `void` kan je nog `return;` doen, bij `never` niet\n * je ziet dat onderstaand voorbeeld een syntaxfout geeft\n"
],
"outputs": []
},
{
"language": "typescript",
"source": [
"function testVreemd(): void {\n return;\n}\n\nfunction test(): never {\n return;\n}"
],
"outputs": []
},
{
"language": "markdown",
"source": [
"Er zijn ook enkele types voor de OO-mensen onder ons:\n\n* `class`\n* `interface`\n* `enum`\n* `type` (minst OO van allemaal)\n\n> `interface` en `type` zijn waarschijnlijk het meest nuttig voor Codifly\n> Hou rekening met wat wel/niet kan met beiden: <https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/basic_type_example#useful-table-for-types-vs-interfaces>\n>\n> Regel: gebruik een `interface` tot je een `type` nodig hebt (bron: [orta](https://twitter.com/orta/status/1356129195835973632?s=20))\n"
],
"outputs": []
},
{
"language": "markdown",
"source": [
"## Type inference\n\nHet is niet altijd verplicht om elke variabele, functie... te typeren. TypeScript is slim genoeg om het type af te leiden uit de context, dit heet **type inference**. Met het keyword `typeof` kan je het type van een variabele opvragen, maar dat geeft niet altijd nuttige info (zie `f`).\n"
],
"outputs": []
},
{
"language": "typescript",
"source": [
"let a = 1;\nlet b = \"hello\";\nlet c = true;\nlet d = null;\nlet e = undefined;\nlet f = [1, 2, 3];\nlet g = { a: 1, b: 2, c: 3 };\n\nconsole.log('Type of a:', typeof a);\nconsole.log('Type of b:', typeof b);\nconsole.log('Type of c:', typeof c);\nconsole.log('Type of d:', typeof d); // nja, null is niet echt een object\nconsole.log('Type of e:', typeof e);\nconsole.log('Type of f:', typeof f); // eigenlijk is dit number[]\nconsole.log('Type of g:', typeof g); // eigenlijk willen we hier ook een mooier type\n\n"
],
"outputs": []
},
{
"language": "markdown",
"source": [
"Een andere waarde toekennen aan een variabele is ook een vorm van type inference. TypeScript laat hierbij niet toe dat je een waarde toekent die niet overeenkomt met het type van de variabele. Afhankelijk van de instellingen van de compiler zal dit een fout of een waarschuwing geven.\n"
],
"outputs": []
},
{
"language": "typescript",
"source": [
"a = \"test\";\n\nconsole.log('Type of a:', typeof a);\n\n// Hier lukt het nu wel maar we krijgen wel een warning, compiler settings kunnen hier een error van maken"
],
"outputs": []
},
{
"language": "markdown",
"source": [
"Je zou ook types kunnen toekennen aan de variabelen door gebruik te maken van de `:` operator. Dit is niet verplicht, maar kan wel handig zijn om de code leesbaarder te maken."
],
"outputs": []
},
{
"language": "typescript",
"source": [
"let getal: number = 1;\nlet tekst: string = \"hello\";\n// ..."
],
"outputs": []
},
{
"language": "markdown",
"source": [
"Het is wel mogelijk om een variable meerdere types te laten aannemen. Dit kan door een `|` te gebruiken tussen de types."
],
"outputs": []
},
{
"language": "typescript",
"source": [
"let getalOfTekst: number | string = 1;\n\n// en dan later:\ngetalOfTekst = \"hello\";"
],
"outputs": []
},
{
"language": "markdown",
"source": [
"Je kan het zelfs nog wat complexer maken:"
],
"outputs": []
},
{
"language": "typescript",
"source": [
"let x = [1, \"hello\", null];\n// het type van x is (number | string | null)[]"
],
"outputs": []
},
{
"language": "markdown",
"source": [
"In de documentatie van TypeScript kan je ook lezen dat type inference in de omgekeerde richting ook werkt, dit heet **contextual typing**. Zie hiervoor <https://www.typescriptlang.org/docs/handbook/type-inference.html#contextual-typing>"
],
"outputs": []
},
{
"language": "markdown",
"source": [
"Je kan ook gedetailleerde types maken voor bijvoorbeeld objecten. Dit kan door gebruik te maken van de `{}` operator. Je kan hiervoor ook een **type alias** maken door gebruik te maken van het `type` keyword."
],
"outputs": []
},
{
"language": "typescript",
"source": [
"const obj1: { a: number, b: string } = { a: 1, b: \"hello\" };\n\n// of\ntype MyObject = { a: number, b: string }; // of een interface\nconst obj2: MyObject = { a: 1, b: \"hello\" };"
],
"outputs": []
},
{
"language": "markdown",
"source": [
"Er zijn ook programmeurs die meer houden van een OO-aanpak. Daarvoor voorziet TypeScript ook een aantal keywords\n\n* `class`: om een klasse te maken\n* `interface`: om een interface te maken\n* `enum`: om een enum te maken"
],
"outputs": []
},
{
"language": "typescript",
"source": [
"enum Kleur { Rood, Groen, Blauw };\n\ninterface Kaart {\n naam: string;\n kleur: Kleur;\n}\n\nclass Persoon {\n naam: string;\n\n constructor(naam: string) {\n this.naam = naam;\n }\n}\n\n// of korter:\nclass Persoon2 {\n constructor(public naam: string) {\n }\n}"
],
"outputs": []
},
{
"language": "markdown",
"source": [
"Je kan hier dus ook keywords als `extends` en `implements` gebruiken om respectievelijk te erven van een klasse/interface of een interface te implementeren.\n\nJe kan aan de constructor van een klasse `private`, `public`, `protected` argumenten meegeven. Dit is syntactic sugar voor het aanmaken van properties met dezelfde naam en het toekennen van de argumenten aan de properties (zie `Persoon2`)."
],
"outputs": []
},
{
"language": "markdown",
"source": [
"## TS config\n\nOm een nieuw TypeScript project te maken, doe je volgende stappen:\n\n1. Maak een nieuwe map aan\n2. Maak een NodeJS project aan met `yarn init`\n3. Voeg TypeScript toe met `yarn add typescript`\n4. Maak een standaard TypeScript config aan met `yarn tsc --init`, dit maakt een `tsconfig.json` bestand aan\n\nEen aantal interessante opties in de `tsconfig.json`:\n\n* `compilerOptions`: de opties van de TS compiler (eigenlijk fout woord want het is geen compiler maar een transpiler)\n* `compilerOptions.target`: de JavaScript-versie waarnaar je wil compileren\n* `compilerOptions.module`: het soort module de compiler zal genereren\n* `compilerOptions.allowJs`: of je JavaScript mag gebruiken in je TypeScript project, handig om te migreren van JS naar TS\n* `compilerOptions.lib`: voeg extra libraries toe aan de standaard ES-libraries\n* `compilerOptions.outDir`: de output directory (waar de JS code terecht komt)\n* `compilerOptions.rootDir`: de root directory (waar de TS code staat), een gelijkaardige structuur zal ook in de `outDir` staan\n* `compilerOptions.experimentalDecorators`: of je decorators mag gebruiken (is nog een experimentele feature)\n* `compilerOptions.jsx`: maak .js bestanden waarin de JSX wordt omgezet naar JavaScript met React.Element\n\nTypeScript bevat ook heel wat [handige opties](https://www.typescriptlang.org/tsconfig) om de code te controleren op stijl, fouten, ... Echter is het aangeraden om hiervoor een linter, zoals [ESLint](https://eslint.org/), te gebruiken. Hierbij moet wel opgemerkt worden dat ESLint niets kan doen tijdens het compileren, het is enkel een linter die je manueel kan uitvoeren. Eventueel kan je ESLint integreren in een CI/CD pipeline die de code controleert vooraleer deze gecompileerd wordt.\n"
],
"outputs": []
}
]
}