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

typescript_evolution_ngonair.pdf

 typescript_evolution_ngonair.pdf

ng on air 用の加筆版

Yosuke Kurami

April 02, 2019
Tweet

More Decks by Yosuke Kurami

Other Decks in Programming

Transcript

  1. 5ZQF4DSJQU
    &WPMVUJPO
    IUNMDPOGFSFODFOHKBQBOPOBJS
    CZ!2VSBNZ

    View Slide

  2. "CPVUNF
    w ૔ݟ༸ีBLB!2VSBNZ
    w ϑϩϯτΤϯυΤϯδχΞ
    w ීஈ͸3FBDU3FEVY ͱ'MPX

    Ͱ8FCΞϓϦॻ͍ͯ·͢

    View Slide

  3. ๻ͱ5ZQF4DSJQU
    w ΋ͱ΋ͱ"OHVMBS͕޷͖
    w ೥݄ʹ(PPHMF͕ʮ"OHVMBSY͸5ZQF4DSJQUʹ͢
    ΔΘʔʯͱએݴͨ͠λΠϛϯάͰ5ZQF4DSJQUʹڵຯΛ࣋ͭ
    w Ͱ΋7JNͰॻ͖͔ͨͬͨͷͰɺQMVHJOͭ͘Δ

    IUUQTHJUIVCDPN2VSBNZUTVRVZPNJ
    w ࢓ࣄͰ΋UTॻ͖ͨ͘ͳͬͯϑϩϯτʹδϣϒνΣϯ

    View Slide

  4. View Slide

  5. "HFOEB
    5ZQF4DSJQU֓ཁ
    ͜͜೥ͷ৽ػೳ$PNQJMFSฤ
    ͜͜೥ͷ৽ػೳ-BOHVBHF4FSWJDFฤ

    View Slide

  6. 5ZQF4DSJQU֓ཁ

    View Slide

  7. 5ZQF4DSJQUͱ͸
    w IUUQTXXXUZQFTDSJQUMBOHPSH
    w .JDSPTPGU͕։ൃͨ͠"MU+BWB4DSJQU

    ओཁͳઃܭऀʹ"OEFST)FKMTCFSH͕͍Δ
    w ੩తͳܕ෇ݴޠ
    w #PPUTUSBQQJOH
    w ΤσΟλϑϨϯυϦʔ

    View Slide

  8. ܕνΣοΫͱਪ࿦
    w ؔ਺TVNͷ໭Γ஋͸OVNCFSͰ͋Δ͜ͱΛਪ࿦͢Δ
    function sum(a: number, b: number) {
    return a + b;
    }
    console.log(sum(1, sum(1, 1))); // OK
    // Argument of type '"a"' is not assignable to
    // parameter of type 'number'
    console.log(sum('a', 'b'));

    View Slide

  9. 4USVDUVBM4VCUZQJOH
    w 5ZQF4DSJQU͸ߏ଄త෦෼ܕΛ࠾༻͍ͯ͠Δ
    w %VDL5ZQJOHͷܕόʔδϣϯͷΑ͏ͳ΋ͷ
    w ܕͷܧঝؔ܎͸ؾʹͤͣɺܕ͕΋͍ͬͯΔϝιουɾϓϩ
    ύςΟͷ߹கͷΈΛؾʹ͢Δ

    View Slide

  10. 4USVDUVBM4VCUZQJOH
    class Hoge {
    name = "Kurami";
    }
    class Foo {
    name = "Quramy";
    }
    function sayHello(obj: { name: string }) {
    console.log(obj.name);
    }
    sayHello(new Hoge());
    sayHello(new Foo());
    sayHello(new Error("error"));

    View Slide

  11. ༨ஊ
    /PNJOBMʹ͍ͨ͠ͱ͖
    w ͨ·ʹߏ଄త෦෼ܕͩͱࠔΔ͜ͱ͕͋Δ
    w QSJWBUFϑΟʔϧυΛ࢖͏ϋοΫͰճආ͢Δ
    class DateISOString {
    private _ = Symbol("DateISOString");
    readonly isoString = new Date().toISOString();
    }
    function hoge(x: DateISOString) {
    console.log(x.isoString);
    }
    hoge(new DateISOString());
    hoge({ isoString: "hoge" }); // Error

    View Slide

  12. 4USJDUDIFDL
    w TUSJDUΦϓγϣϯʢσϑΥϧτͰPOʣΛ෇͚͓ͯ͘ͱɺݎ
    ࿚ͳνΣοΫ͕Մೳʹ
    function hoge(x?: string) {
    //Object is possibly 'undefined'.
    return x.trim();
    }
    function hoge(x?: string) {
    if (!x) return "";
    return x.trim(); // OK
    }

    View Slide

  13. BMMPXKTDIFDLKT
    w ৽͘͠ϓϩδΣΫτΛ࡞Δͱ͖͸ɺTUSJDUͰΑ͍
    w Ұํɺطଘͷ+BWB4DSJQUϓϩδΣΫτʹ5ZQF4DSJQUΛಋೖ
    ͢Δ͜ͱ΋Մೳ
    w BMMPXKTDIFDLKTΦϓγϣϯΛPOʹ͢ΔͱɺUT͚ͩͰ
    ͳ͘ɺKTϑΝΠϧΛѻ͏͜ͱ΋Ͱ͖ΔͷͰɺগͣͭ͠UT΁
    ஔ͖׵͑Δ͜ͱ͕Ͱ͖Δ

    View Slide

  14. ϥΠϒϥϦͷܕఆٛ
    w ༗໊ͳϥΠϒϥϦ͸OQNJ!UZQFϥΠϒϥϦ໊Ͱܕఆٛ
    ͕ެ։͞Ε͍ͯΔ
    npm i @types/node
    import path from "path";
    export function hoge() {
    const x = path.join("src", "main.ts");
    }

    View Slide

  15. !UZQFT
    w IUUQTHJUIVCDPN%FpOJUFMZ5ZQFE%FpOJUFMZ5ZQFE

    View Slide

  16. 3FMFBTFDZDMF
    w ϲ݄पظͰϚΠφʔόʔδϣϯ͕VQEBUF͞Ε͍ͯ͘
    w ηϚϯςΟοΫόʔδϣϯχϯάͰ͸ͳ͍
    w ͷΑ͏ͳNJOPSVQEBUFͰ͋ͬͯ΋ɺഁյతม
    ߋ͕ՃΘΔ͜ͱ΋͋Δ
    w CMPHͰഁյతมߋʹ͍ͭͯΞφ΢ϯε͕͋ΔͷͰɺͦΕΛ
    ΑΜͰ͔ΒVQEBUF͢ΔͱΑ͍

    View Slide

  17. #SFBLJOH$IBOHFT

    View Slide

  18. 5$ͱͷ݉Ͷ߹͍
    w جຊతʹ5$ͰTUBHFʹͳͬͨ࢓༷͕औΓࠐ·ΕΔ
    w ྫ
    w /VNFSJD4FQBSBUPS
    w #JH*OU
    const i = 60_000;

    View Slide

  19. ͍͔ͭ͘ͷྫ֎
    w FYQFSJNFOUBM%FDPSBUPS FNJU%FDPSBUPS.FUBEBUB
    w WY͔Βར༻Մೳɻ"OHVMBS͸͜Ε͕ͳ͍ͱ੒Γཱͨ
    ͳ͍
    w KTYSFBDU
    w WY͔Βར༻ՄೳɻΈΜͳେ޷͖+49

    View Slide

  20. ͜͜೥ͷ৽ػೳ
    $PNQJMFSฤ

    View Slide

  21. $PNQJMFS

    View Slide

  22. FT.PEVMF*OUFSPQ

    View Slide

  23. FT.PEVMFT*OUFSPQ
    w ೥Նࠒʹ/PEFKTͷ&4.PEVMFTʹ͍ͭͯͷऔѻʹಈ
    ͖͕͋ͬͨͷΛड͚ͯɺWYͰಋೖ͞ΕͨΦϓγϣϯ
    w ৄ͘͠͸IUUQTUFQQFJTIBUFOBCMPHDPNFOUSZ
    FTNPEVMFTJOOPEFKTͳͲΛࢀর
    w &4.PEVMFT͔Β$PNNPO+4NPEVMFΛJNQPSU͢Δࡍ͸
    EFGBVMUJNQPSUΛ࢖ΘͶ͹ͳΒͳ͍

    View Slide

  24. FT.PEVMFT*OUFSPQ
    w /PEFKTͰ͸ɺ$PNNPO+4͔ΒOBNFEJNQPSU͢ΔͱΤ
    ϥʔʹ
    /* hoge.mjs */
    import { readFile } from "fs";
    $ node --experimental-modules hoge.mjs
    SyntaxError: The requested module does not provide an export
    named ‘readFile'
    at checkComplete (internal/loader/ModuleJob.js:75:27)
    at moduleJob.linked.then (internal/loader/ModuleJob.js:
    58:11)
    at

    View Slide

  25. FT.PEVMFT*OUFSPQ
    w Ұํɺ5ZQF4DSJQUͰ͸ඇ&4.PEVMFT͔ΒͷEFGBVMU
    JNQPSU͸ར༻Ͱ͖ͳ͔ͬͨͨΊɺ$PNNPO+4ΛJNQPSU͢
    Δʹ͸ɺOBNFEJNQPSUͰهड़͢Δ͔͠ͳ͔ͬͨ
    import * as fs from "fs";
    import { readFile } from "fs";

    View Slide

  26. FT.PEVMFT*OUFSPQ
    w WYҎ߱Ͱ͸ɺ$PNNPO+4͔ΒͷEFGBVMUJNQPSU͕ڐ༰͞
    ΕΔΑ͏ʹͳͬͨ
    w ैདྷͷOBNFEJNQPSUͷॻ͖ํ΋ґવڐ༰͸͞Ε͍ͯΔ΋ͷ
    ͷɺ5ZQF4DSJQU΋ެࣜʹEFGBVMUJNQPSUͷॻ͖ํΛਪ঑ͯ͠
    ͍Δɻ

    IUUQTXXXUZQFTDSJQUMBOHPSHEPDTIBOECPPLSFMFBTF
    OPUFTUZQFTDSJQUIUNMTVQQPSUGPSJNQPSUEGSPN
    DKTGPSNDPNNPOKTNPEVMFTXJUIFTNPEVMFJOUFSPQ
    import fs from "fs";

    View Slide

  27. *NQSPWF.BQQFE
    5ZQF.PEJpFS

    View Slide

  28. .BQQFE5ZQF.PEJpFS
    w WYͰಋೖ
    w ैདྷͷ.BQQFE5ZQFͰ͸ɺSFBEPOMZ Λ෇༩͢Δ͜ͱ
    ͸Ͱ͖ͯ΋ɺղআ͢Δ͜ͱ͸Ͱ͖ͳ͔ͬͨ
    type Optional = {
    [P in keyof T]?: T[P]
    };
    type ReadOnly = {
    readonly [P in keyof T]: T[P]
    };

    View Slide

  29. XJUINPEJpFS
    w ͷ෇༩Ͱɺ࡞༻ͷ޲͖ ෇͚Δ֎͢
    ΛදݱՄೳʹ
    type Optional = {
    [P in keyof T]+?: T[P]
    };
    type Strict = {
    [P in keyof T]-?: T[P]
    };
    type ReadOnly = {
    +readonly [P in keyof T]: T[P]
    };
    type Mutable = {
    -readonly [P in keyof T]: T[P]
    };

    View Slide

  30. XJUINPEJpFS
    type Strict = {
    [P in keyof T]-?: T[P]
    };
    // Property 'name' is missing in type '{}'
    // but required in type 'Strictundefined; }>'.
    const x: Strict = { };

    View Slide

  31. $POEJUJPOBMUZQFT

    View Slide

  32. $POEJUJPOBMUZQFT
    w WYͰಋೖ
    w "TTJHOBCMFΛ৚݅ͱͯ͠෼ذ͢ΔܕΛදݱՄೳ
    w ʮܕ5͕ܕ6ͷ෦෼ܕͰ͋Ε͹ɺܕ9ɺͦ͏Ͱͳ͚Ε͹ܕ:ʯ
    ͱ͍͏ҙຯ
    type MyType = T extends U ? X : Y;

    View Slide

  33. -FUTUZQF
    w ༡ΜͰΈΑ͏$POEJUJPOBM5ZQFT
    w %J⒎
    w %J⒎͸ͲΜͳܕͰ͠ΐ͏͔ʁ
    type DiffKey = K1 extends K2 ? never : K1;
    type $Diff = {
    [P in DiffKey]: T[P];
    };

    View Slide

  34. %JTUSJCVUJPO
    w $POEJUJPOBM5ZQFTͱ6OJPO5ZQFTͷؒʹ͸෼഑཯͕੒ཱ
    w OFWFS͸͍͔ͳΔܕʹ΋୅ೖෆՄೳͳܕʢϘτϜܕʣ
    w
    type DiffKey = K1 extends K2 ? never : K1;
    let key: DiffKey;
    // ("name" extends "age" ? never : "name")
    // | ("age" extends "age" ? never : "age")
    // = ("name" | never)
    // = "name"

    View Slide

  35. $POEJUJPOJONBQQFEUZQFT
    w %J⒎,FZLFZPG5 LFZPG6͸ʮܕ5ͷLFZશମ͔Βɺܕ6
    ͷLFZશମͷू߹ΛҾ͍ͨू߹ʯ
    w .BQQFE5ZQF͸͋ΔLFZͷू߹ʹର͢ΔϓϩύςΟͷϚο
    ϐϯά
    type $Diff = {
    [P in DiffKey]: T[P];
    };

    View Slide

  36. %J⒎ͷਖ਼ମ
    w 'MPXUZQFʹಉ໊ͷ6UJMJUZUZQF͕͋Γ·͢
    type DiffKey = K1 extends K2 ? never : K1;
    type $Diff = {
    [P in DiffKey]: T[P];
    };
    const defaultProps = { age: 0 };
    let requiredProps: $Diffname: string;
    age: number;
    }, typeof defaultProps>;
    requiredProps = { name: "Quramy" };

    View Slide

  37. 5ZQFJOGFSFODFJO

    DPOEJUJPOBMUZQFT

    View Slide

  38. 5ZQFJOGFSFODFJO
    DPOEJUJPOBMUZQFT
    w WYͰ$POEJUJPOBM5ZQFTͱಉ࣌ʹϦϦʔε͞Εͨػೳ
    w $POEJUJPOBM5ZQFTͷ৚݅෦෼ʹͯϚονϯά࣌ʹਪ࿦͞
    ΕͨܕΛ࠶ར༻Ͱ͖ΔΑ͏ʹ
    T extends MyCondition ? SomeType : Y;

    View Slide

  39. *OGFSBOE$BQUVSF
    w ਖ਼نදݱͷΩϟϓνϟϦϯάʢάϧʔϓԽʣͱࣅ͍ͯΔ
    w Ϛονͨ͠άϧʔϓ෦෼Λޙ͔Βར༻Ͱ͖Δ
    const regexp = /hoge(\d+)/;
    const hit = "hoge10".match(regexp);
    console.log(hit[1]) // 10

    View Slide

  40. *OGFSBOE$BQUVSF
    w 5͕ؔ਺Ͱ͋Ε͹ɺͦͷ໭Γ஋ͱͯ͠ਪ࿦͞ΕΔܕ͕3ʹ֨
    ೲ͞ΕΔ
    type Return =
    T extends (...args: any[]) => infer R ? R : never;
    let r: Return number>; // typeof r = number

    View Slide

  41. 3FEVYͬΆ͍ΞϨ
    type Return =
    T extends (...args: any[]) => infer R ? R : never;
    type AppState = { [P in keyof T]: Return };
    const reducers = {
    name: (state: string, action: any) => state,
    age: (state: number, action: any) => state,
    };
    let appState: AppState;
    // typeof appState = { name: sting, age: number }

    View Slide

  42. ࢖͍͗͢ʹ஫ҙ
    w $POEJUJPOBM5ZQFTͱ5ZQF*OGFSFODF SZʹΑͬͯɺطଘ
    ͷܕఆ͔ٛΒ৽͘͠ܕΛ࡞Δखஈ͕֨ஈʹ޲্
    w ॻ͍ͯΔͱ͖͸ύζϧײ֮Ͱָ͍͠΋ͷͷɺద౓ͳ༻๏ɾ
    ༰ྔΛ৺͕͚ͨ΄͏͕Α͍
    w Τϥʔϝοηʔδ͕ͲΜͲΜಡΈͮΒ͘ͳΔ
    w ϨϏϡΞ͕ͨ·ͬͨ΋Μ͡Όͳ͍

    View Slide

  43. VOLOPXO

    View Slide

  44. VOLOPXOUZQF
    w WYͰಋೖ
    w VOLOPXO͸͢΂ͯͷܕ͕BTTJHOBCMF
    w VOLOPXOUZQF͸ɺUZQFBTTFSUJPO͠ͳ͍ͱԿ΋Ͱ͖ͳ͍
    function hoge(x: unknown) {
    if (typeof x === "string") {
    console.log(x.toLowerCase());
    }
    }
    hoge(10);
    hoge("foo");

    View Slide

  45. 5VQMFTJOSFTUQBSBNFUFST
    BOETQSFBEFYQSFTTJPOT

    View Slide

  46. 5VQMFTJOSFTUQBSBNFUFST
    BOETQSFBEFYQSFTTJPOT
    w WYͰɺؔ਺Ҿ਺ʹؔ܎͢Δܕͷهड़ྗ͕ڧԽ͞Εͨ
    w 3FTUQBSBNFUFSTXJUIUVQMFUZQFT
    w 4QSFBEFYQSFTTJPOTXJUIUVQMFUZQFT
    w (FOFSJDSFTUQBSBNFUFST
    w 0QUJPOBMFMFNFOUTJOUVQMFUZQFT
    w 3FTUFMFNFOUTJOUVQMFUZQFT

    View Slide

  47. 3FTUQBSBNFUFSTXJUI
    UVQMFUZQFT
    w WYҎલ͸3FTU1BSBNFUFS͸"SSBZUZQFͷΈ͕ڐ༰
    w WY͔Β͸5VQMFUZQF΋ར༻Մೳʹ
    function hoge(...args: any[]) {
    const a1 = args[0];
    const a2 = args[1];
    const a3 = args[2];
    }
    function foo(...args: [string, number]) {
    const a0 = args[0]; // string
    const a1 = args[1]; // number
    const a2 = args[2]; // error
    }

    View Slide

  48. 4QSFBEFYQSFTTJPOTXJUI
    UVQMFUZQFT
    w 4QSFBE0QFSBUPSʹΑΔؔ਺ݺͼग़͠ʹରԠ

    Ҏલ͸DPNQJMFFSSPSʹͳͬͯ͠·͍ͬͯͨ

    w WY͔Β͸5VQMFUZQF΋ར༻Մೳʹ
    declare function foo(a: number, b: number): void;
    const args1 = [1, 2] as [number, number];
    foo(...args1);
    const args2 = [1, "bar" ] as [number, string];
    // Argument of type 'string' is not assignable to
    // parameter of type 'number'.
    foo(...args2);

    View Slide

  49. (FOFSJDSFTUQBSBNFUFST
    w 3FTU1BSBNFUFSTʹ૯শܕ͕ར༻Մೳʹ
    w +BWB4DSJQUGVODUJPOͷCJOEDBMMBQQMZͱͷ਌࿨ੑ޲্

    ޙड़ͷTUSJDU#JOE$BMM"QQMZͷૅ

    declare function curry(
    fn: (x: T, ...args: U) => R
    ): (x: T) => (...args: U) => R;
    const sum = (a: number, b: number) => a + b;
    const bound = curry(sum)(1);
    const x = bound(2); // type of x = number
    const error = bound("hoge"); // error

    View Slide

  50. 0QUJPOBMFMFNFOUTJOUVQMF
    UZQFT
    w 5VQMF5ZQFͷதͰ NPEJpFS͕ར༻Մೳʹ
    w 3FTU1BSBNFUFSTΛ5VQMF5ZQFͰड͚ΕΔΑ͏ͳͬͨ͜
    ͱʹΑΔ෭࢈෺
    type Tuple = [number, string?];
    const x1: Tuple = [1];
    const x2: Tuple = [1, "foo"];

    View Slide

  51. 3FTUFMFNFOUTJOUVQMF
    UZQFT
    w 5VQMF5ZQFதʹ3FTUͳUZQFΛදݱͰ͖ΔΑ͏ʹͳͬͨ
    w ؔ਺ͷ3FTU1BSBNFUFSTͱͯ͠΋ར༻Մೳ
    function hoge(...args: T) {
    return args;
    }
    const arr = [1, 2, 3];
    const v = hoge("hoge", ...arr);
    // typeof v = [string, ...number[]]
    type Hoge = [string, ...number[]];

    View Slide

  52. .BQQFEUVQMFUZQFT

    View Slide

  53. .BQQFEUVQMFUZQFT
    w WYͰಋೖ
    w WY·Ͱ͸.BQQFE5ZQFʹ"SSBZ-JLFͳ5ZQFΛ৯Θͤ
    ͯ΋ɺ΄΅ҙຯͷͳ͍݁Ռʹͳ͍ͬͯͨ
    w WY͔Β͸ʮ഑ྻཁૉࣗମʹର͢ΔϚοϐϯάʯͱ͍͏
    ڍಈʹมߋ͞Εͨ

    View Slide

  54. Y
    type Box = { value: V };
    type Boxing= {
    [P in keyof T]: Box;
    };
    type User = {
    name: string,
    age: number,
    };
    const boxedUser: Boxing = {
    name: { value: "quramy" },
    age: { value: 18 },
    };
    let boxedNumbers: Boxing;
    boxedNumbers.concat.value([]); // ???
    boxedNumbers.length.value; // ???

    View Slide

  55. Y
    w LFZPGOVNCFS<>ͷҙຯ͕มΘͬͨΘ͚Ͱ͸ͳ͍఺ʹ஫ҙ
    type Box = { value: V };
    type Boxing= {
    [P in keyof T]: Box;
    };
    const boxedNumbers: Boxing = [
    { value: 1 },
    { value: 100 },
    ];

    View Slide

  56. ࢖͍Έͪ
    w $POEJUJPOBMUZQF (FOFSJDSFTUQBSBNFUFST .BQQFE
    UVQMFUZQFͷ߹ΘٕͤͷྫΛ঺հ
    w ͓୊SYKTͷDPNCJOF-BUFTUؔ਺ʢ˞1SPNJTFBMMతͳౕʣ
    interface Observable {
    subscribe(cb: (v: T) => void): void;
    }
    declare var s1$: Observable;
    declare var s2$: Observable;
    combineLatest(s1$, s2$).subscribe(([s1, s2]) => {
    console.log(s1); // typeof s1 = string
    console.log(s2); // typeof s2 = number
    });

    View Slide

  57. ࢖͍Έͪ
    interface Observable {
    subscribe(cb: (v: T) => void): void;
    }
    // Inference in conditional type
    type StreamType =
    T extends Observable ? S : never;
    // Mapped tuple type
    type Unboxing[]> = {
    [P in keyof U]: StreamType;
    };
    // Generic rest parameters
    declare function combineLatest[]>
    (...args: U): Observable>;

    View Slide

  58. TUSJDU#JOE$BMM"QQMZ

    View Slide

  59. TUSJDU#JOE$BMM"QQMZ
    w WYͰಋೖ
    w GVODUJPOͷCJOEDBMMBQQMZʹର͢ΔνΣοΫ͕ݫີԽ
    w WYͷ5VQMFUZQF3FTUQBSBNFUFSTڧԽͷ෭࢈෺
    w TUSJDUΦϓγϣϯϑΝϛϦʔͷͭʢσϑΥϧτͰ0/ʣ

    View Slide

  60. TUSJDU#JOE$BMM"QQMZ
    w CJOE
    declare function hoge(a: number, b: string): void
    const hoge1 = hoge.bind(null, 1);
    hoge1("hoge");
    hoge1(); // error
    hoge1(1); // error
    hoge1("hoge", 2); // error

    View Slide

  61. TUSJDU#JOE$BMM"QQMZ
    w DBMM
    declare function hoge(a: number, b: string): void
    hoge.call(null, 1, "hoge");
    hoge.call(null, 1); // error
    hoge.call(null, "hoge"); // error
    hoge.call(null, 1, "hoge", 2); // error

    View Slide

  62. TUSJDU#JOE$BMM"QQMZ
    w BQQMZ
    declare function hoge(a: number, b: string): void
    hoge.apply(null, [1, "hoge"]);
    hoge.apply(null, [1]); // error
    hoge.apply(null, ["hoge"]); // error
    hoge.apply(null, [1, "hoge", 2]); // error

    View Slide

  63. )JHIFSPSEFSGVODUJPO
    UZQFJOGFSFODF

    View Slide

  64. )JHIFSPSEFSGVODUJPOUZQF
    JOGFSFODF
    w WͰಋೖ
    w ૯শܕΛؚΉؔ਺ΛҾ਺΍໭Γ஋ʹ͢Δؔ਺ʢ͍ΘΏΔ൚
    ؔ਺ʣͷܕਪ࿦͕Մೳʹͳͬͨ
    w ԿΛݴ͍ͬͯΔͷ͔Θ͔Βͳ͍

    View Slide

  65. ͜͏͍͏͜ͱΒ͍͠
    declare function pipe(
    ab: (...args: A) => B,
    bc: (b: B) => C
    ): (...args: A) => C;
    declare function list(a: T): T[];
    declare function box(x: V): { value: V };
    const listBox = pipe(list, box); // (a: T) => { value: T[] }
    const boxList = pipe(box, list); // (x: V) => { value: V }[]
    const x1 = listBox(42); // { value: number[] }
    const x2 = boxList("hello"); // { value: string }[]
    w ैདྷ͸ɺMJTU#PY͸(a: any) => { value: any[] } ʹͳͬ
    ͯ͠·ͬͨ

    View Slide

  66. ࠓߋײ͋Δ΍ͭ
    import { ComponentType } from "react";
    type HoC = (c: ComponentType) => ComponentType;
    declare function compose(
    hoc1: HoC,
    hoc2: HoC,
    ): (c: ComponentType) => ComponentType;

    View Slide

  67. import { ComponentType } from "react";
    type $Diff = { [P in Exclude]: T[P] };
    // HoCs
    declare function connect(c: ComponentType): ComponentType>;
    declare function withRouter(c: ComponentType): ComponentType>;
    type Props = {
    className: string,
    location: Location,
    count: number,
    };
    declare function MyComponent(props: Props): JSX.Element; // render props component
    const enhancer = compose(
    connect,
    withRouter,
    );
    const MyContainer = enhancer(MyComponent);
    const App = () => ; // Outer Props͕ਪ࿦͞ΕΔ

    View Slide

  68. ͜͜೥ͷ৽ػೳ

    -BOHBHF4FSWJDFฤ

    View Slide

  69. -BOHVBHF4FSWJDF

    View Slide

  70. 0SHBOJ[F*NQPSU

    View Slide

  71. 0SHBOJ[F*NQPSU
    w WYͰಋೖ
    w UTTFSWFS -BOHVBHF4FSWJDF
    ʹPSHBOJ[F*NQPSUίϚϯ
    υ͕௥Ճ͞Εͨ
    w UTMJOUͷOPVOVTFEWBSJBCMFT JNQPSU
    ͷpY૬౰΋΍ͬͯ͘
    ΕΔ

    View Slide

  72. %FNP
    /* before */
    import { hoge } from "./lib";
    import { foo } from "./lib";
    // no used import
    import { bar } from "./lib";
    hoge();
    foo();
    /* after */
    import { hoge, foo } from "./lib";
    hoge();
    foo();

    View Slide

  73. $PEF'JY4VHHFTUJPO

    View Slide

  74. ,JOEPG&SSPST
    w 5ZQF4DSJQUͷΤϥʔ͸΋ͱ΋ͱछྨ
    w 4ZOUBY&SSPSͦ΋ͦ΋จ๏ͱ͓͔͍ͯ͠͠΋ͷ
    w 4FNBOUJD&SSPSܕෆ੔߹ͳͲ

    View Slide

  75. &SSPS$PEFpY
    w UTTFSWFS -BOHVBHF4FSWJDF
    ʹ͓͚ΔΤϥʔpYͷྲྀΕ
    HFU4VQQPSUFE$PEF'JYFTίϚϯυͰ-BOH4FSWJDF͕ରԠՄೳͳ
    ΤϥʔίʔυͷҰཡΛऔಘ͓ͯ͘͠
    HFU&SSPSίϚϯυͰϑΝΠϧͷΤϥʔΛ-BOH4FSWJDF΁໰͍߹Θ
    ͤΔ
    $PEF'JYαϙʔτର৅ͷΤϥʔίʔυͷ৔߹ɺHFU$PEF'JYFTίϚ
    ϯυͰमਖ਼಺༰Λ-BOH4FSWJDFʹ໰͍߹ΘͤΔ
    ड͚औͬͨมߋ಺༰ 5FYU$IBOHF
    ΛΤσΟλͷόοϑΝʹద༻͢Δ

    View Slide

  76. 4VHHFTUJPO&SSPS
    w ཁ͢ΔʹΤϥʔ͕ແ͍ͱɺ$PEF'JY͸Ͱ͖ͳ͍
    w ʮ5ZQF4DSJQUͦͷ΋ͷ͕ਪ঑͢Δॻ͖ํʯʹϦϑΝΫλ͞
    ͤΔͨΊʹ͸ɺରԠ͢ΔΤϥʔίʔυ͕ඞཁ
    w Α͠ɺ৽͍͠ΧςΰϦΛ࡞Ζ͏ʂͱ͍͏͜ͱͰɺ
    4VHHFTUJPO&SSPS͕WYͰੜ·Εͨ

    View Slide

  77. %FNP
    w ౾஌ࣝ
    Τϥʔίʔυ൪୆͸4VHHFTUJPO&SSPS

    View Slide

  78. 3FOBNFJNQPSU
    EFDMBSBUJPO

    View Slide

  79. 3FOBNFJNQPSU
    EFDMBSBUJPO
    w WYͰಋೖ
    w *NQPSUGSPNͷର৅෦෼ΛSFOBNFͰ͖ΔΑ͏ʹͳͬͨ
    /* fuga.ts */
    export function fuga() {
    return "hoge";
    }
    /* main.ts */
    import { fuga } from "./fuga";
    console.log(hoge());

    View Slide

  80. 4VNNBSZ

    View Slide

  81. 4VNNBSZ
    w $POEJUJPOBMUZQFͱ*OGFSFODF͸௒ڧྗ
    w 3FTUQBSBNFUFSTपΓͷվળ͕ҰؾʹਐΜͩ

    CJOEDBMMBQQMZͷܕνΣοΫ͸਱ʹདྷ͔ͨʂײ͋Δ
    w $PEF'JY΍ϦϑΝΫλؔ࿈΋Ҿ͖ଓ͖֦ॆ͕ਐΜͰ͍Δ

    View Slide

  82. &OKPZUZQJOH
    5ZQF4DSJQU

    View Slide

  83. 5IBOLZPV

    View Slide