Slide 1

Slide 1 text

Ginpei.dev By Ginpei Takanashi https://Ginpei.dev Start TypeScript . Leaving JavaScript as JS JSConf JP December 1st 2019

Slide 2

Slide 2 text

Ginpei.dev • This slide is designed for presentation. PDF would not make sence. • I’m preparing an article for it. Stay tuend! • このスライドはプレゼン用です。PDFだけだとわかりづらいと 思います。 • 記事用意してるのでお待ちくださいませ。 ⚠️ Caution ご注意 ⚠️

Slide 3

Slide 3 text

Ginpei.dev Target Individual Job AIに支配される人達のイラスト | かわいいフリー素材集 いらすとや https://www.irasutoya.com/2016/08/ai.html オフィスのイラスト | かわいいフリー素材集 いらすとや https://www.irasutoya.com/2014/05/blog-post_6681.html 不良集団のイラスト | かわいいフリー素材集 いらすとや https://www.irasutoya.com/2019/07/blog-post_37.html 通帳を見て青ざめる人のイラスト(男性) | かわいいフリー素材集 いらすとや https://www.irasutoya.com/2017/08/blog-post_880.html https://github.com/remojansen/logo.ts Target

Slide 4

Slide 4 text

Ginpei.dev /** * @param {Size} size */ function setSize(size) {} /** @type {string | null} */ let id = null; /** * @typedef {{ * height: number; * width: number; * }} Size */ Agenda • Add comments to declare types in JS files • TYPE IS AWESOME o Improves your coding speed o Supports your refactoring • Use `tsc` as a type linter o With `--checkJs` option • Less cost than converting JS to TS • Individual usage possible

Slide 5

Slide 5 text

Ginpei.dev I’m Ginpei / ギンペイです From Vancouver, Canada Love JavaScript & JapaneseSushi 世界地図のイラスト | かわいいフリー素材集 いらすとや https://www.irasutoya.com/2013/02/blog-post_8574.html

Slide 6

Slide 6 text

How TypeScript is AWESOME https://www.instagram.com/p/BK7xJ8Dhca-/

Slide 7

Slide 7 text

Ginpei.dev • TypeScript is superset of JavaScript • TypeScript has types How TypeScript is AWESOME

Slide 8

Slide 8 text

Ginpei.dev Syntax hierarchy TypeScript JavaScript JSON

Slide 9

Slide 9 text

Ginpei.dev function greeter(person) { return "Hello, " + person; } let user = "Jane User"; document.body.textContent = greeter(user); JavaScript is-a TypeScript Via TypeScript in 5 minutes · TypeScript https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html

Slide 10

Slide 10 text

Ginpei.dev function greeter(person: string) { return "Hello, " + person; } let user = "Jane User"; document.body.textContent = greeter(user); Types Via TypeScript in 5 minutes · TypeScript https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html

Slide 11

Slide 11 text

Ginpei.dev However…

Slide 12

Slide 12 text

When TypeScript does not work https://www.instagram.com/p/_QrC5oicoa/

Slide 13

Slide 13 text

Ginpei.dev In some cases, its tough to add TS step into the current bundler Traditional Long-life Build System tsc 本能寺のイラスト | かわいいフリー素材集 いらすとや https://www.irasutoya.com/2017/01/blog-post_0.html 鹿に鹿せんべいを上げる人のイラスト | かわいいフリー素材集 いらすとや https://www.irasutoya.com/2018/10/blog-post_31.html

Slide 14

Slide 14 text

Ginpei.dev In some cases, its tough to add TS step into the current bundler 本能寺の変のイラスト | かわいいフリー素材集 いらすとや https://www.irasutoya.com/2017/01/blog-post_16.html 鹿に襲われる人のイラスト | かわいいフリー素材集 いらすとや https://www.irasutoya.com/2018/10/blog-post_38.html

Slide 15

Slide 15 text

Ginpei.dev On the other hand, team may feel uncomfortable with TypeScript いらすとや https://www.irasutoya.com/2014/10/blog-post_89.html https://www.irasutoya.com/2014/10/blog-post_35.html https://www.irasutoya.com/2017/08/blog-post_915.html https://www.irasutoya.com/2018/06/crt.html https://www.irasutoya.com/2014/04/blog-post_7628.html remojansen/logo.ts https://github.com/remojansen/logo.ts

Slide 16

Slide 16 text

Ginpei.dev On the other hand, team may feel uncomfortable with TypeScript いらすとや https://www.irasutoya.com/2014/10/blog-post_89.html https://www.irasutoya.com/2014/10/blog-post_35.html https://www.irasutoya.com/2017/08/blog-post_915.html https://www.irasutoya.com/2018/06/crt.html https://www.irasutoya.com/2014/04/blog-post_7628.html remojansen/logo.ts https://github.com/remojansen/logo.ts

Slide 17

Slide 17 text

Ginpei.dev Even if there are no build steps FFFTP Project Top Page - OSDN https://osdn.net/projects/ffftp/ 田舎の村のイラスト(過疎) | かわいいフリー素材集 いらすとや https://www.irasutoya.com/2017/06/blog-post_392.html

Slide 18

Slide 18 text

Ginpei.dev OK no worries, Typed-JavaScript is here!!! /** * @param {Size} size */ function setSize(size) {} /** @type {string | null} */ let id = null; /** * @typedef {{ * height: number; * width: number; * }} Size */

Slide 19

Slide 19 text

Thank Buddha we have Typed- JavaScript https://www.instagram.com/p/BG8cTclick8/

Slide 20

Slide 20 text

Ginpei.dev • Typed-JavaScript is definitely JavaScript • Typed-JavaScript has types Typed-JavaScript is AWESOME

Slide 21

Slide 21 text

Ginpei.dev TypeScript vs Typed-JavaScript function setSize(size: Size) {} let id: string | null = null; let Size = { height: number; width: number; } /** * @param {Size} size */ function setSize(size) {} /** @type {string | null} */ let id = null; /** * @typedef {{ * height: number; * width: number; * }} Size */

Slide 22

Slide 22 text

Ginpei.dev You could start typing alone $ npm install typescript --global $ npx tsc

Slide 23

Slide 23 text

Ginpei.dev /** * @param {Size} size */ function setSize(size) {} /** @type {string | null} */ let id = null; /** * @typedef {{ * height: number; * width: number; * }} Size */ Typed-JavaScript is definitely JavaScript

Slide 24

Slide 24 text

Ginpei.dev Static validation

Slide 25

Slide 25 text

Ginpei.dev Compiler shows errors

Slide 26

Slide 26 text

Ginpei.dev setSize({ height: 123, width: 234, }); Guess parameter: number?

Slide 27

Slide 27 text

Ginpei.dev setSize({ height: 'auto', width: '234px', }); Guess parameter: CSS props?

Slide 28

Slide 28 text

Ginpei.dev setSize({ height: { value: 123, unit: 'px' }, width: { value: 234, unit: 'px' }, }); Guess parameter: complex object?

Slide 29

Slide 29 text

Ginpei.dev Static validation: in terminal

Slide 30

Slide 30 text

Ginpei.dev Static validation: in editor

Slide 31

Slide 31 text

Ginpei.dev Powerful suggestions within editor

Slide 32

Slide 32 text

Ginpei.dev Suggesting properties

Slide 33

Slide 33 text

Ginpei.dev Find correct props

Slide 34

Slide 34 text

Ginpei.dev Identifying arguments

Slide 35

Slide 35 text

Ginpei.dev Strong refactoring support

Slide 36

Slide 36 text

Ginpei.dev const book = { auther: 'Ginpei Takanashi', name: 'JavaScript for Adélie Penguins', publishedAt: new Date('2019/12/01'), }; Will you be satisfied by this code?

Slide 37

Slide 37 text

Ginpei.dev const book = { auther: 'Ginpei Takanashi', name: 'JavaScript for Adélie Penguins', publishedAt: new Date('2019/12/01'), }; Do you want to correct typo?

Slide 38

Slide 38 text

Ginpei.dev const book = { auther: 'Ginpei Takanashi', name: 'JavaScript for Adélie Penguins', publishedAt: new Date('2019/12/01'), }; Do you want to rename better?

Slide 39

Slide 39 text

Ginpei.dev const book = { auther: 'Ginpei Takanashi', name: 'JavaScript for Adélie Penguins', publishedAt: new Date('2019/12/01'), }; Do you want to alternate type?

Slide 40

Slide 40 text

Ginpei.dev You might overlook without compiler

Slide 41

Slide 41 text

Ginpei.dev You won’t with compiler

Slide 42

Slide 42 text

Ginpei.dev Refactoring: rename

Slide 43

Slide 43 text

Add types into your code https://en.wikipedia.org/wiki/File:McDonalds_Canada.svg https://www.instagram.com/p/BaDkpLAnedd/

Slide 44

Slide 44 text

Ginpei.dev Have a compiler read JS files

Slide 45

Slide 45 text

Ginpei.dev $ npm install typescript $ npx tsc --init message TS6071: Successfully created a tsconfig.json file. Install and set up

Slide 46

Slide 46 text

Ginpei.dev { "compilerOptions": { /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'E "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 's // "lib": [], /* Specify library files to be included in the compilation. */ // "allowJs": true, /* Allow javascript files to be compiled. */ // "checkJs": true, /* Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react- // "declaration": true, /* Generates corresponding '.d.ts' file. */ // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ // "sourceMap": true, /* Generates corresponding '.map' file. */ // "outFile": "./", /* Concatenate and emit output to single file. */ … Generated `tsconfig.json` file

Slide 47

Slide 47 text

Ginpei.dev { "compilerOptions": { "allowJs": true, // read *.js "checkJs": true, // check types in JS "noEmit": true, // only type-checking "strict": true, // enable nice type-checking options }, "include": ["./js"], // target files "exclude": ["./js/lib"] // not-target files } Example `tsconfig.json`

Slide 48

Slide 48 text

Ginpei.dev // @ts-nocheck import { Book } from "./Book"; export default function MyComponent(props) { return (

Hello World!

); } Skip error report for a file

Slide 49

Slide 49 text

Ginpei.dev // @ts-nocheck import { Book } from "./Book"; export default function MyComponent(props) { return (

Hello World!

); } Skip error report for a file

Slide 50

Slide 50 text

Ginpei.dev { "compilerOptions": { "allowJs": true, // read *.js - "checkJs": true, // check types in JS + // "checkJs": true, // check types in JS "noEmit": true, // only type-checking "strict": true, // enable nice type-checking options }, } Check types in specific files

Slide 51

Slide 51 text

Ginpei.dev // @ts-check import { Book } from "./Book"; export default function MyComponent(props) { return (

Hello World!

); } Report error for each file

Slide 52

Slide 52 text

Ginpei.dev // @ts-check import { Book } from "./Book"; export default function MyComponent(props) { return (

Hello World!

); } Report error for each file

Slide 53

Slide 53 text

Ginpei.dev { "compilerOptions": { "allowJs": true, // read *.js "checkJs": true, // check types in JS - "noEmit": true, // only type-checking + "outDir": "./out", "strict": true, // enable nice type-checking options }, } Use TypeScript together * In default src/index.ts ↓ src/index.js

Slide 54

Slide 54 text

Ginpei.dev Add types in comments

Slide 55

Slide 55 text

Ginpei.dev // TypeScript function setSize(size: Size): boolean {} Functions // JavaScript /** * @param {Size} size * @returns {boolean} */ function setSize(size) {}

Slide 56

Slide 56 text

Ginpei.dev // TypeScript function isSize(size: any): size is Size {} Functions (type guard) // JavaScript /** * @param {any} size * @returns {size is Size} */ function isSize(size) {}

Slide 57

Slide 57 text

Ginpei.dev // TypeScript let id: string | null = null; Variables // JavaScript /** @type {string | null} */ let id = null;

Slide 58

Slide 58 text

Ginpei.dev // TypeScript const elInput = document.querySelector('#input') as HTMLInputElement; Expressions with cast // JavaScript /** @type {HTMLInputElement} */ const elInput = (document.querySelector('#input'));

Slide 59

Slide 59 text

Ginpei.dev // TypeScript const map = new Map(); Variable with Generics // JavaScript /** @type {Map} */ const map = new Map();

Slide 60

Slide 60 text

Ginpei.dev // TypeScript type ItemId = string | null; Types (simple) // JavaScript /** * @typedef {string | null} ItemId */

Slide 61

Slide 61 text

Ginpei.dev // TypeScript type Size = { height: number; width: number; } Types (complex) // JavaScript /** * @typedef {{ * height: number; * width: number; * }} Size */

Slide 62

Slide 62 text

Ginpei.dev // TypeScript import { Size } from './path/to'; Import types

Slide 63

Slide 63 text

Ginpei.dev // TypeScript type Size = import('./lib').Size; Import types // JavaScript /** * @typedef {import('./path/to').Size} Size */

Slide 64

Slide 64 text

Ginpei.dev // TypeScript function wrap(item: T | T[]) { return item instanceof Array ? item : [item]; } Generics (template)

Slide 65

Slide 65 text

Ginpei.dev // JavaScript /** * @template T * @param {T | T[]} item * @returns {T[]} */ function wrap (item) { return item instanceof Array ? item : [item]; } Generics (template)

Slide 66

Slide 66 text

Ginpei.dev // TypeScript function findById(arr: T[], id: string) { return arr.find((v) => v.id === id); } Generics (template) (extends)

Slide 67

Slide 67 text

Ginpei.dev // JavaScript /** * @template {{ id: string }} T * @param {T[]} arr * @param {string} id */ function findById (arr, id) { return arr.find((v) => v.id === id); } Generics (template) (extends)

Slide 68

Slide 68 text

Ginpei.dev // TypeScript function foo() {} // JavaScript //

Slide 69

Slide 69 text

Ginpei.dev // @ts-ignore const $ = window.jQuery; Skip error report for line

Slide 70

Slide 70 text

Ginpei.dev // @ts-ignore const $ = window.jQuery; Skip error report for line

Slide 71

Slide 71 text

Ginpei.dev Add missing declarations

Slide 72

Slide 72 text

Ginpei.dev • `npm install @types/jquery` • Create own `./types/jquery.d.ts` Add missing declarations

Slide 73

Slide 73 text

Ginpei.dev Recap: Add types into your code • Functions o`@param` o`@returns` • Variables o`@type` o`(exp)` to cast • Types o`@typedef` o`import()` • Generics o`@template` • Skip error report o `// @ts-ignore`

Slide 74

Slide 74 text

Advanced typing https://www.instagram.com/p/Bdwn4-fnfhE/

Slide 75

Slide 75 text

Ginpei.dev // TypeScript const book = { author: 'Ginpei Takanashi', title: 'JavaScript for Adélie Penguins', publishedAt: new Date('2019/12/01'), }; type Book = typeof book; `typeof` type Book = { author: string; title: string; publishedAt: Date; }

Slide 76

Slide 76 text

Ginpei.dev // TypeScript const book = { author: 'Ginpei Takanashi', title: 'JavaScript for Adélie Penguins', publishedAt: new Date('2019/12/01'), }; /** * @typedef {typeof book} Book */ `typeof`

Slide 77

Slide 77 text

Ginpei.dev function buildLargeObject() { return { foo: { hoge: 123 }, bar: [true, false, true], run() { return true; }, /** * @param {string} destination */ walk(destination) {}, }; } /** * @typedef {ReturnType} LargeObject */ Util: `ReturnType` type LargeObject = { foo: { hoge: number; }; bar: boolean[]; run(): boolean; walk(destination: string): void; }

Slide 78

Slide 78 text

Ginpei.dev /** @type {ReturnType} */ let timer = 0; Util: `ReturnType`

Slide 79

Slide 79 text

Ginpei.dev /** * @param {FooOptions} options */ function foo(options) {} /** @type {Parameters[0]} */ const options = {}; foo(options); Util: `Paramerters[i]`

Slide 80

Slide 80 text

Ginpei.dev /** * Obtain the parameters of a constructor function type in a tuple */ type ConstructorParameters any> = T extends new (...args: infer P) => any ? P : never; Util: `ConstructorParameters`

Slide 81

Slide 81 text

Ginpei.dev type AnyObject = T & { [key: string]: any; } const book: AnyObject> = {}; book.author = getAuthor(); Any object

Slide 82

Slide 82 text

Ginpei.dev type PickAngularService = ReturnType>; namespace App { type MyService = PickAngularService } e.g. AngularJS Service Type

Slide 83

Slide 83 text

Downsides https://www.instagram.com/p/BZsJcFcHbFc/

Slide 84

Slide 84 text

Ginpei.dev Much code function setSize(size: Size) {} let id: string | null = null; let Size = { height: number; width: number; } /** * @param {Size} size */ function setSize(size) {} /** @type {string | null} */ let id = null; /** * @typedef {{ * height: number; * width: number; * }} Size */

Slide 85

Slide 85 text

Ginpei.dev // TypeScript const elInput = document.querySelector('#input'); const elementMap = new Map(); No runtime generics

Slide 86

Slide 86 text

Ginpei.dev // TypeScript if (map.has('xxx')) { return map.get('xxx')!; } No non-null assertion `!` operators

Slide 87

Slide 87 text

Ginpei.dev No default types in generics // JavaScript // // TypeScript function foo() {}

Slide 88

Slide 88 text

Conclusion https://www.instagram.com/p/53Ut_qCcja/

Slide 89

Slide 89 text

Ginpei.dev /** * @param {Size} size */ function setSize(size) {} /** @type {string | null} */ let id = null; /** * @typedef {{ * height: number; * width: number; * }} Size */ Recap • Add comments to declare types in JS files • TYPE IS AWESOME o Improves your coding speed o Supports your refactoring • Use `tsc` as a type linter o With `--checkJs` option • Easy to get started • Enjoy typing!

Slide 90

Slide 90 text

Ginpei.dev ご清聴ありがとうございました。 高梨ギンペイでした。 16日まで日本にいます。 https://Ginpei.dev @ginpei_en, @ginpei_jp @ginpei Thanks! Presented by Ginpei