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

Start TypeScript Leaving JavaScript as JS

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Start TypeScript Leaving JavaScript as JS

Avatar for Ginpei Takanashi

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!