mirror of
https://github.com/microsoft/frontend-bootcamp.git
synced 2026-01-26 14:56:42 +08:00
adding documentation
This commit is contained in:
204
docs/step2-01/README.md
Normal file
204
docs/step2-01/README.md
Normal file
@@ -0,0 +1,204 @@
|
||||
# Step 2.1: Introduction to Typescript
|
||||
|
||||
[Lessons](../) | [Exercise](./exercise/) | [Demo](./demo/)
|
||||
|
||||
In this step, we'll cover enough of the Typescript concepts to be productive with the React & Redux frameworks.
|
||||
|
||||
Topics in this step will include:
|
||||
|
||||
- ES modules
|
||||
- Basic Types
|
||||
- Interfaces & Classes
|
||||
- Basic Generics
|
||||
- Spread and Destructuring
|
||||
- Async / Await
|
||||
|
||||
## Modules
|
||||
|
||||
Historically, JS is only executed in browser. The code all had to be loaded from `<script>` tags. Since the introduction of node.js, the JS community needed a way to scale beyond just single script files. Other language support the notion of modules. There are many JS modularity standards today.
|
||||
|
||||
The most important ones to know about are:
|
||||
|
||||
- commonjs - Node.js's standard to support modules
|
||||
- synchronous
|
||||
- require() function, can be dynamically called in the course of a program
|
||||
- ESM (Ecmascript module) - language level support
|
||||
- statically analyzable and synchronous
|
||||
- dynamic and asynchronous support via `import()` that returns a promise
|
||||
|
||||
## Typescript Types
|
||||
|
||||
Refer to the `demo/src` for some examples of some of the types avaible in TS that benefits a React developer.
|
||||
|
||||
## Spread Syntax
|
||||
|
||||
Spread syntax allows for quick way to clone and concatenate objects and arrays. This syntax is seen a lot inside React props and Redux reducers.
|
||||
|
||||
To shallow copy something:
|
||||
|
||||
```ts
|
||||
const cloned = { ...obj };
|
||||
```
|
||||
|
||||
To shallow copy and add / overwrite a key:
|
||||
|
||||
```ts
|
||||
const overridden = { ...obj, key: value };
|
||||
```
|
||||
|
||||
You can have an expression to calculate this key if it is dynamic:
|
||||
|
||||
```ts
|
||||
const overridden = { ...object, [key + '-suffix']: value };
|
||||
```
|
||||
|
||||
## Destructuring
|
||||
|
||||
Destructuring is a concise way to take properties out of an object or array:
|
||||
|
||||
```ts
|
||||
const obj = { foo: 1, bar: 2 };
|
||||
const { foo, bar } = obj;
|
||||
// foo = 1, bar = 2
|
||||
```
|
||||
|
||||
Same thing for array:
|
||||
|
||||
```ts
|
||||
const arr = [1, 2];
|
||||
const [foo, bar] = arr;
|
||||
// foo = 1, bar = 2
|
||||
```
|
||||
|
||||
You can separate an item and the rest of the object with destructuring:
|
||||
|
||||
```ts
|
||||
const obj = { a: 1, b: 2, c: 3, d: 4 };
|
||||
const { a, ...rest } = obj;
|
||||
// a = 1, rest = {b: 2, c: 3, d: 4}
|
||||
```
|
||||
|
||||
# Promise
|
||||
|
||||
A promise is an object that represent work that will be completed later, asynchronously. It is a chainable so writing async code is maintainable. Typically legacy async code uses callback to let the caller have control over what to do after the task has been completed.
|
||||
|
||||
```ts
|
||||
const aPromise = new Promise((resolve, reject) => {
|
||||
// do something async and call resolve() to let promise know it is done
|
||||
|
||||
setTimeout(() => {
|
||||
// setTimeout will call this method after 1s, simulating async operation like network calls
|
||||
resolve();
|
||||
}, 1000);
|
||||
});
|
||||
```
|
||||
|
||||
The promise object exposes a `then()` function that is chainable. `catch()` is present that catches all exceptions or `reject()` calls:
|
||||
|
||||
```ts
|
||||
const aPromise = Promise.resolve('hello world'); /* ... just an example promise */
|
||||
|
||||
aPromise
|
||||
.then(result => {
|
||||
return makeAnotherPromise();
|
||||
})
|
||||
.then(result => {
|
||||
return makeYetAnotherPromise();
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
```
|
||||
|
||||
# Async / Await
|
||||
|
||||
This syntax is inspired heavily by C#'s async / await syntax. To write an async function write it like this:
|
||||
|
||||
```ts
|
||||
async function someFunctionAsync() {
|
||||
// Inside here, we can await on other async functions
|
||||
const result = await someOtherFunctionAsync();
|
||||
return result + ' hello';
|
||||
}
|
||||
```
|
||||
|
||||
All functions that are marked `async` return a `Promise` automatically. This previous example returned a `Promise<string>`, and can be used like this:
|
||||
|
||||
```ts
|
||||
someFunctionAsync().then(result => {
|
||||
console.log(result);
|
||||
});
|
||||
```
|
||||
|
||||
# Exercise
|
||||
|
||||
Please complete all exercises inside the `exercise/src` folder unless otherwise specified in the exercises below. First, open up [Step2-01 exercise page](http://localhost:8080/step2-01/exercise/) to see the results while you're implementing things.
|
||||
|
||||
## Modules
|
||||
|
||||
1. Open up file called `index.ts` in VS Code
|
||||
|
||||
2. Create another module file called `fibonacci.ts`
|
||||
|
||||
3. Inside the file from (step 2), write a function called `fib(n)` that takes in a number and returns a the n-th Fibonacci number - be sure the specify the type of n
|
||||
|
||||
> HINT: fib(n) = fib(n - 1) + fib(n - 2); fib(n <= 1) = n;
|
||||
|
||||
4. Export `fib(n)` as a **named export**
|
||||
|
||||
5. Export another const variable as a **default export**
|
||||
|
||||
6. Import both the modules created in steps (4) and (5) and use the provided `log()` function to log it onto the page.
|
||||
|
||||
## Types, Interfaces, and Classes
|
||||
|
||||
Create inside `index.ts`:
|
||||
|
||||
1. a type alias for string union type describing the states of Red-Green-Yellow traffic light: `type TrafficLight = ???`
|
||||
|
||||
2. describe a type of car with an interface: `interface Car { ... }`
|
||||
|
||||
## Generic
|
||||
|
||||
Inside `stack.ts`, create a generic class for a `Stack<T>` complete with a typed `pop()` and `push()` methods
|
||||
|
||||
> Hint: the Javascript array already has `push()` and `pop()` implemented for you. That can be your backing store.
|
||||
|
||||
Be sure to use the provided `log()` to show the functionality of `Stack<T>`
|
||||
|
||||
## Spread and Destructure
|
||||
|
||||
1. Note the following code in index.ts:
|
||||
|
||||
```ts
|
||||
const obj1 = {
|
||||
first: 'who',
|
||||
second: 'what',
|
||||
third: 'dunno',
|
||||
left: 'why'
|
||||
};
|
||||
|
||||
const obj2 = {
|
||||
center: 'because',
|
||||
pitcher: 'tomorrow',
|
||||
catcher: 'today'
|
||||
};
|
||||
```
|
||||
|
||||
2. Now create a one-liner using the spread syntax `{...x, ...y}` to create a new variable that combines these two objects.
|
||||
|
||||
3. Using the destructuring syntax to retrieve the values for `{first, second, catcher}` from this new object created in step (2).
|
||||
|
||||
## Async / Await
|
||||
|
||||
1. Note the following code in index.ts:
|
||||
|
||||
```ts
|
||||
function makePromise() {
|
||||
return Promise.resolve(5);
|
||||
}
|
||||
```
|
||||
|
||||
2. call `makePromise()` with the `await` syntax and log the results using the provided `log()` function
|
||||
|
||||
3. create a new function that uses the `async` keyword to create an async function. Make an await call to `makePromise()` and return the results
|
||||
@@ -1,6 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script src="../../step2-01/demo/step2-01/demo.js"></script></body>
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../assets/step.css" />
|
||||
</head>
|
||||
<body class="ms-Fabric">
|
||||
<div id="markdownReadme"></div>
|
||||
<div id="app">
|
||||
Nothing to show here, just look at your console window for output. Hit F12 to open console window.
|
||||
</div>
|
||||
<script src="../../step2-01/demo/step2-01/demo.js"></script><script src="../../markdownReadme/markdownReadme.js"></script></body>
|
||||
</html>
|
||||
|
||||
@@ -1,20 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100vh;
|
||||
height: 100vh;
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="../../assets/step.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script src="../../step2-01/exercise/step2-01/exercise.js"></script></body>
|
||||
<body class="ms-Fabric">
|
||||
<div id="markdownReadme"></div>
|
||||
<div id="app">
|
||||
Nothing to show here, just look at your console window for output. Hit F12 to open console window.
|
||||
</div>
|
||||
<script src="../../step2-01/exercise/step2-01/exercise.js"></script><script src="../../markdownReadme/markdownReadme.js"></script></body>
|
||||
</html>
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
const app = document.getElementById('app');
|
||||
const textarea = document.createElement('textarea');
|
||||
textarea.setAttribute('readonly', 'true');
|
||||
app.appendChild(textarea);
|
||||
function log(results: string) {
|
||||
textarea.innerText += results;
|
||||
}
|
||||
|
||||
// Some setup code for exercises
|
||||
const obj1 = {
|
||||
first: 'who',
|
||||
@@ -24,11 +16,13 @@ function makePromise() {
|
||||
return Promise.resolve(5);
|
||||
}
|
||||
|
||||
// Do the exercises here, output your results with "log()" function
|
||||
// Do the exercises here, output your results with "console.log()" function
|
||||
// ...
|
||||
log('hello world');
|
||||
console.log('hello world');
|
||||
|
||||
(async () => {
|
||||
async function run() {
|
||||
// Place your code for the async / await exercise here
|
||||
// ...
|
||||
})();
|
||||
}
|
||||
|
||||
run();
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
/*! no static exports found */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
eval("var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar __generator = (this && this.__generator) || function (thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (_) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n};\nvar _this = this;\nvar app = document.getElementById('app');\nvar textarea = document.createElement('textarea');\ntextarea.setAttribute('readonly', 'true');\napp.appendChild(textarea);\nfunction log(results) {\n textarea.innerText += results;\n}\n// Some setup code for exercises\nvar obj1 = {\n first: 'who',\n second: 'what',\n third: 'dunno',\n left: 'why'\n};\nvar obj2 = {\n center: 'because',\n pitcher: 'tomorrow',\n catcher: 'today'\n};\nfunction makePromise() {\n return Promise.resolve(5);\n}\n// Do the exercises here, output your results with \"log()\" function\n// ...\nlog('hello world');\n(function () { return __awaiter(_this, void 0, void 0, function () {\n return __generator(this, function (_a) {\n return [2 /*return*/];\n });\n}); })();\n\n\n//# sourceURL=webpack:///./step2-01/exercise/src/index.ts?");
|
||||
eval("var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar __generator = (this && this.__generator) || function (thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (_) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n};\n// Some setup code for exercises\nvar obj1 = {\n first: 'who',\n second: 'what',\n third: 'dunno',\n left: 'why'\n};\nvar obj2 = {\n center: 'because',\n pitcher: 'tomorrow',\n catcher: 'today'\n};\nfunction makePromise() {\n return Promise.resolve(5);\n}\n// Do the exercises here, output your results with \"console.log()\" function\n// ...\nconsole.log('hello world');\nfunction run() {\n return __awaiter(this, void 0, void 0, function () {\n return __generator(this, function (_a) {\n return [2 /*return*/];\n });\n });\n}\nrun();\n\n\n//# sourceURL=webpack:///./step2-01/exercise/src/index.ts?");
|
||||
|
||||
/***/ })
|
||||
|
||||
|
||||
Reference in New Issue
Block a user