Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Start TypeScript Leaving JavaScript as JS

Start TypeScript Leaving JavaScript as JS

Ginpei Takanashi

December 01, 2019
Tweet

Other Decks in Technology

Transcript

  1. Ginpei.dev • This slide is designed for presentation. PDF would

    not make sence. • I’m preparing an article for it. Stay tuend! • このスライドはプレゼン用です。PDFだけだとわかりづらいと 思います。 • 記事用意してるのでお待ちくださいませ。 ⚠️ Caution ご注意 ⚠️
  2. 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
  3. 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
  4. Ginpei.dev I’m Ginpei / ギンペイです From Vancouver, Canada Love JavaScript

    & JapaneseSushi 世界地図のイラスト | かわいいフリー素材集 いらすとや https://www.irasutoya.com/2013/02/blog-post_8574.html
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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
  10. 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
  11. 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
  12. 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 */
  13. 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 */
  14. 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
  15. Ginpei.dev setSize({ height: { value: 123, unit: 'px' }, width:

    { value: 234, unit: 'px' }, }); Guess parameter: complex object?
  16. 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?
  17. 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?
  18. 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?
  19. 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?
  20. Ginpei.dev $ npm install typescript $ npx tsc --init message

    TS6071: Successfully created a tsconfig.json file. Install and set up
  21. 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
  22. 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`
  23. Ginpei.dev // @ts-nocheck import { Book } from "./Book"; export

    default function MyComponent(props) { return ( <div> <h1>Hello World!</h1> </div> ); } Skip error report for a file
  24. Ginpei.dev // @ts-nocheck import { Book } from "./Book"; export

    default function MyComponent(props) { return ( <div> <h1>Hello World!</h1> </div> ); } Skip error report for a file
  25. 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
  26. Ginpei.dev // @ts-check import { Book } from "./Book"; export

    default function MyComponent(props) { return ( <div> <h1>Hello World!</h1> </div> ); } Report error for each file
  27. Ginpei.dev // @ts-check import { Book } from "./Book"; export

    default function MyComponent(props) { return ( <div> <h1>Hello World!</h1> </div> ); } Report error for each file
  28. 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
  29. Ginpei.dev // TypeScript function setSize(size: Size): boolean {} Functions //

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

    Functions (type guard) // JavaScript /** * @param {any} size * @returns {size is Size} */ function isSize(size) {}
  31. Ginpei.dev // TypeScript let id: string | null = null;

    Variables // JavaScript /** @type {string | null} */ let id = null;
  32. Ginpei.dev // TypeScript const elInput = document.querySelector('#input') as HTMLInputElement; Expressions

    with cast // JavaScript /** @type {HTMLInputElement} */ const elInput = (document.querySelector('#input'));
  33. Ginpei.dev // TypeScript const map = new Map<string, string>(); Variable

    with Generics // JavaScript /** @type {Map<string, string>} */ const map = new Map();
  34. Ginpei.dev // TypeScript type ItemId = string | null; Types

    (simple) // JavaScript /** * @typedef {string | null} ItemId */
  35. Ginpei.dev // TypeScript type Size = { height: number; width:

    number; } Types (complex) // JavaScript /** * @typedef {{ * height: number; * width: number; * }} Size */
  36. Ginpei.dev // TypeScript type Size = import('./lib').Size; Import types //

    JavaScript /** * @typedef {import('./path/to').Size} Size */
  37. Ginpei.dev // TypeScript function wrap<T>(item: T | T[]) { return

    item instanceof Array ? item : [item]; } Generics (template)
  38. Ginpei.dev // JavaScript /** * @template T * @param {T

    | T[]} item * @returns {T[]} */ function wrap (item) { return item instanceof Array ? item : [item]; } Generics (template)
  39. Ginpei.dev // TypeScript function findById<T extends { id: string }>(arr:

    T[], id: string) { return arr.find((v) => v.id === id); } Generics (template) (extends)
  40. 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)
  41. 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`
  42. 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; }
  43. 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`
  44. Ginpei.dev function buildLargeObject() { return { foo: { hoge: 123

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

    /** @type {Parameters<foo>[0]} */ const options = {}; foo(options); Util: `Paramerters<fn>[i]`
  46. Ginpei.dev /** * Obtain the parameters of a constructor function

    type in a tuple */ type ConstructorParameters<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never; Util: `ConstructorParameters<fn>`
  47. Ginpei.dev type AnyObject<T = {}> = T & { [key:

    string]: any; } const book: AnyObject<Partial<Book>> = {}; book.author = getAuthor(); Any object
  48. Ginpei.dev type PickAngularService<T extends any[]> = ReturnType<Exclude<T[0], string>>; namespace App

    { type MyService = PickAngularService<typeof import('path/to/lib')> } e.g. AngularJS Service Type
  49. 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 */
  50. 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!