$30 off During Our Annual Pro Sale. View Details »

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
    By Ginpei Takanashi
    https://Ginpei.dev
    Start TypeScript
    .
    Leaving JavaScript as JS
    JSConf JP
    December 1st 2019

    View Slide

  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 ご注意 ⚠️

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  8. Ginpei.dev
    Syntax hierarchy
    TypeScript
    JavaScript
    JSON

    View Slide

  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

    View Slide

  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

    View Slide

  11. Ginpei.dev
    However…

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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
    */

    View Slide

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

    View Slide

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

    View Slide

  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
    */

    View Slide

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

    View Slide

  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

    View Slide

  24. Ginpei.dev
    Static validation

    View Slide

  25. Ginpei.dev
    Compiler shows errors

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  29. Ginpei.dev
    Static validation: in terminal

    View Slide

  30. Ginpei.dev
    Static validation: in editor

    View Slide

  31. Ginpei.dev
    Powerful suggestions
    within editor

    View Slide

  32. Ginpei.dev
    Suggesting properties

    View Slide

  33. Ginpei.dev
    Find correct props

    View Slide

  34. Ginpei.dev
    Identifying arguments

    View Slide

  35. Ginpei.dev
    Strong
    refactoring support

    View Slide

  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?

    View Slide

  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?

    View Slide

  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?

    View Slide

  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?

    View Slide

  40. Ginpei.dev
    You might overlook without compiler

    View Slide

  41. Ginpei.dev
    You won’t with compiler

    View Slide

  42. Ginpei.dev
    Refactoring: rename

    View Slide

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

    View Slide

  44. Ginpei.dev
    Have a compiler
    read JS files

    View Slide

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

    View Slide

  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

    View Slide

  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`

    View Slide

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

    Hello World!

    );
    }
    Skip error report for a file

    View Slide

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

    Hello World!

    );
    }
    Skip error report for a file

    View Slide

  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

    View Slide

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

    Hello World!

    );
    }
    Report error for each file

    View Slide

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

    Hello World!

    );
    }
    Report error for each file

    View Slide

  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

    View Slide

  54. Ginpei.dev
    Add types
    in comments

    View Slide

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

    View Slide

  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) {}

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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)

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  71. Ginpei.dev
    Add missing declarations

    View Slide

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

    View Slide

  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`

    View Slide

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

    View Slide

  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;
    }

    View Slide

  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`

    View Slide

  77. 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;
    }

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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
    */

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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!

    View Slide

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

    View Slide