Start TypeScript Leaving JavaScript as JS

Start TypeScript Leaving JavaScript as JS

1597308a3a44e946461dc086c6efc5b8?s=128

Takanashi, Ginpei

December 01, 2019
Tweet

Transcript

  1. Ginpei.dev By Ginpei Takanashi https://Ginpei.dev Start TypeScript . Leaving JavaScript

    as JS JSConf JP December 1st 2019
  2. Ginpei.dev • This slide is designed for presentation. PDF would

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

    & JapaneseSushi 世界地図のイラスト | かわいいフリー素材集 いらすとや https://www.irasutoya.com/2013/02/blog-post_8574.html
  6. How TypeScript is AWESOME https://www.instagram.com/p/BK7xJ8Dhca-/

  7. Ginpei.dev • TypeScript is superset of JavaScript • TypeScript has

    types How TypeScript is AWESOME
  8. Ginpei.dev Syntax hierarchy TypeScript JavaScript JSON

  9. 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
  10. 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
  11. Ginpei.dev However…

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

  13. 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
  14. 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
  15. 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
  16. 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
  17. 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
  18. 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 */
  19. Thank Buddha we have Typed- JavaScript https://www.instagram.com/p/BG8cTclick8/

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

    Typed-JavaScript is AWESOME
  21. 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 */
  22. Ginpei.dev You could start typing alone $ npm install typescript

    --global $ npx tsc
  23. 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
  24. Ginpei.dev Static validation

  25. Ginpei.dev Compiler shows errors

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

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

    props?
  28. Ginpei.dev setSize({ height: { value: 123, unit: 'px' }, width:

    { value: 234, unit: 'px' }, }); Guess parameter: complex object?
  29. Ginpei.dev Static validation: in terminal

  30. Ginpei.dev Static validation: in editor

  31. Ginpei.dev Powerful suggestions within editor

  32. Ginpei.dev Suggesting properties

  33. Ginpei.dev Find correct props

  34. Ginpei.dev Identifying arguments

  35. Ginpei.dev Strong refactoring support

  36. 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?
  37. 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?
  38. 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?
  39. 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?
  40. Ginpei.dev You might overlook without compiler

  41. Ginpei.dev You won’t with compiler

  42. Ginpei.dev Refactoring: rename

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

  44. Ginpei.dev Have a compiler read JS files

  45. Ginpei.dev $ npm install typescript $ npx tsc --init message

    TS6071: Successfully created a tsconfig.json file. Install and set up
  46. 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
  47. 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`
  48. 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
  49. 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
  50. 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
  51. 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
  52. 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
  53. 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
  54. Ginpei.dev Add types in comments

  55. Ginpei.dev // TypeScript function setSize(size: Size): boolean {} Functions //

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

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

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

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

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

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

    number; } Types (complex) // JavaScript /** * @typedef {{ * height: number; * width: number; * }} Size */
  62. Ginpei.dev // TypeScript import { Size } from './path/to'; Import

    types
  63. Ginpei.dev // TypeScript type Size = import('./lib').Size; Import types //

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

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

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

    T[], id: string) { return arr.find((v) => v.id === id); } Generics (template) (extends)
  67. 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)
  68. Ginpei.dev // TypeScript function foo<T = {}>() {} // JavaScript

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

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

    for line
  71. Ginpei.dev Add missing declarations

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

    missing declarations
  73. 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`
  74. Advanced typing https://www.instagram.com/p/Bdwn4-fnfhE/

  75. 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; }
  76. 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`
  77. 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; }
  78. Ginpei.dev /** @type {ReturnType<Window['setTimeout']>} */ let timer = 0; Util:

    `ReturnType<fn>`
  79. Ginpei.dev /** * @param {FooOptions} options */ function foo(options) {}

    /** @type {Parameters<foo>[0]} */ const options = {}; foo(options); Util: `Paramerters<fn>[i]`
  80. 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>`
  81. Ginpei.dev type AnyObject<T = {}> = T & { [key:

    string]: any; } const book: AnyObject<Partial<Book>> = {}; book.author = getAuthor(); Any object
  82. 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
  83. Downsides https://www.instagram.com/p/BZsJcFcHbFc/

  84. 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 */
  85. Ginpei.dev // TypeScript const elInput = document.querySelector<HTMLInputEle ment>('#input'); const elementMap

    = new Map<string, HTMLElement>(); No runtime generics
  86. Ginpei.dev // TypeScript if (map.has('xxx')) { return map.get('xxx')!; } No

    non-null assertion `!` operators
  87. Ginpei.dev No default types in generics // JavaScript // //

    TypeScript function foo<T = {}>() {}
  88. Conclusion https://www.instagram.com/p/53Ut_qCcja/

  89. 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!
  90. Ginpei.dev ご清聴ありがとうございました。 高梨ギンペイでした。 16日まで日本にいます。 https://Ginpei.dev @ginpei_en, @ginpei_jp @ginpei Thanks! Presented

    by Ginpei