Pro Yearly is on sale from $80 to $50! »

typescript_evolution_ngonair.pdf

 typescript_evolution_ngonair.pdf

ng on air 用の加筆版

893f54413c2bd9ba41d11d753aacaf2c?s=128

Yosuke Kurami

April 02, 2019
Tweet

Transcript

  1. 5ZQF4DSJQU &WPMVUJPO IUNMDPOGFSFODFOHKBQBOPOBJS CZ!2VSBNZ

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

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

    ࢓ࣄͰ΋UTॻ͖ͨ͘ͳͬͯϑϩϯτʹδϣϒνΣϯ
  4. None
  5. "HFOEB  5ZQF4DSJQU֓ཁ  ͜͜೥ͷ৽ػೳ$PNQJMFSฤ  ͜͜೥ͷ৽ػೳ-BOHVBHF4FSWJDFฤ

  6. 5ZQF4DSJQU֓ཁ

  7. 5ZQF4DSJQUͱ͸ w IUUQTXXXUZQFTDSJQUMBOHPSH w .JDSPTPGU͕։ൃͨ͠"MU+BWB4DSJQU
 ओཁͳઃܭऀʹ"OEFST)FKMTCFSH͕͍Δ w ੩తͳܕ෇ݴޠ w #PPUTUSBQQJOH

    w ΤσΟλϑϨϯυϦʔ
  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'));
  9. 4USVDUVBM4VCUZQJOH w 5ZQF4DSJQU͸ߏ଄త෦෼ܕΛ࠾༻͍ͯ͠Δ w %VDL5ZQJOHͷܕόʔδϣϯͷΑ͏ͳ΋ͷ w ܕͷܧঝؔ܎͸ؾʹͤͣɺܕ͕΋͍ͬͯΔϝιουɾϓϩ ύςΟͷ߹கͷΈΛؾʹ͢Δ

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

  14. ϥΠϒϥϦͷܕఆٛ w ༗໊ͳϥΠϒϥϦ͸OQNJ!UZQFϥΠϒϥϦ໊Ͱܕఆٛ ͕ެ։͞Ε͍ͯΔ npm i @types/node import path from

    "path"; export function hoge() { const x = path.join("src", "main.ts"); }
  15. !UZQFT w IUUQTHJUIVCDPN%FpOJUFMZ5ZQFE%FpOJUFMZ5ZQFE

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

    ΑΜͰ͔ΒVQEBUF͢ΔͱΑ͍
  17. #SFBLJOH$IBOHFT

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

    i = 60_000;
  19. ͍͔ͭ͘ͷྫ֎ w FYQFSJNFOUBM%FDPSBUPS FNJU%FDPSBUPS.FUBEBUB w WY͔Βར༻Մೳɻ"OHVMBS͸͜Ε͕ͳ͍ͱ੒Γཱͨ ͳ͍ w KTYSFBDU w

    WY͔Βར༻ՄೳɻΈΜͳେ޷͖+49
  20. ͜͜೥ͷ৽ػೳ $PNQJMFSฤ

  21. $PNQJMFS

  22. FT.PEVMF*OUFSPQ

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

  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 <anonymous>
  25. FT.PEVMFT*OUFSPQ w Ұํɺ5ZQF4DSJQUͰ͸ඇ&4.PEVMFT͔ΒͷEFGBVMU JNQPSU͸ར༻Ͱ͖ͳ͔ͬͨͨΊɺ$PNNPO+4ΛJNQPSU͢ Δʹ͸ɺOBNFEJNQPSUͰهड़͢Δ͔͠ͳ͔ͬͨ import * as fs from

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

    DKTGPSNDPNNPOKTNPEVMFTXJUIFTNPEVMFJOUFSPQ import fs from "fs";
  27. *NQSPWF.BQQFE 5ZQF.PEJpFS

  28. .BQQFE5ZQF.PEJpFS w WYͰಋೖ w ैདྷͷ.BQQFE5ZQFͰ͸ɺSFBEPOMZ Λ෇༩͢Δ͜ͱ ͸Ͱ͖ͯ΋ɺղআ͢Δ͜ͱ͸Ͱ͖ͳ͔ͬͨ type Optional<T> =

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

    in keyof T]+?: T[P] }; type Strict<T> = { [P in keyof T]-?: T[P] }; type ReadOnly<T> = { +readonly [P in keyof T]: T[P] }; type Mutable<T> = { -readonly [P in keyof T]: T[P] };
  30. XJUINPEJpFS type Strict<T> = { [P in keyof T]-?: T[P]

    }; // Property 'name' is missing in type '{}' // but required in type 'Strict<{ name?: string | undefined; }>'. const x: Strict<{ name?: string }> = { };
  31. $POEJUJPOBMUZQFT

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

    U, X, Y> = T extends U ? X : Y;
  33. -FUTUZQF w ༡ΜͰΈΑ͏$POEJUJPOBM5ZQFT w %J⒎ w %J⒎͸ͲΜͳܕͰ͠ΐ͏͔ʁ type DiffKey<K1, K2>

    = K1 extends K2 ? never : K1; type $Diff<T, U> = { [P in DiffKey<keyof T, keyof U>]: T[P]; };
  34. %JTUSJCVUJPO w $POEJUJPOBM5ZQFTͱ6OJPO5ZQFTͷؒʹ͸෼഑཯͕੒ཱ w OFWFS͸͍͔ͳΔܕʹ΋୅ೖෆՄೳͳܕʢϘτϜܕʣ w type DiffKey<K1, K2> =

    K1 extends K2 ? never : K1; let key: DiffKey<("name" | "age"), "age">; // ("name" extends "age" ? never : "name") // | ("age" extends "age" ? never : "age") // = ("name" | never) // = "name"
  35. $POEJUJPOJONBQQFEUZQFT w %J⒎,FZLFZPG5 LFZPG6͸ʮܕ5ͷLFZશମ͔Βɺܕ6 ͷLFZશମͷू߹ΛҾ͍ͨू߹ʯ w .BQQFE5ZQF͸͋ΔLFZͷू߹ʹର͢ΔϓϩύςΟͷϚο ϐϯά type $Diff<T,

    U> = { [P in DiffKey<keyof T, keyof U>]: T[P]; };
  36. %J⒎ͷਖ਼ମ w 'MPXUZQFʹಉ໊ͷ6UJMJUZUZQF͕͋Γ·͢ type DiffKey<K1, K2> = K1 extends K2

    ? never : K1; type $Diff<T, U> = { [P in DiffKey<keyof T, keyof U>]: T[P]; }; const defaultProps = { age: 0 }; let requiredProps: $Diff<{ name: string; age: number; }, typeof defaultProps>; requiredProps = { name: "Quramy" };
  37. 5ZQFJOGFSFODFJO
 DPOEJUJPOBMUZQFT

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

    S> ? SomeType<S> : Y;
  39. *OGFSBOE$BQUVSF w ਖ਼نදݱͷΩϟϓνϟϦϯάʢάϧʔϓԽʣͱࣅ͍ͯΔ w Ϛονͨ͠άϧʔϓ෦෼Λޙ͔Βར༻Ͱ͖Δ const regexp = /hoge(\d+)/; const

    hit = "hoge10".match(regexp); console.log(hit[1]) // 10
  40. *OGFSBOE$BQUVSF w 5͕ؔ਺Ͱ͋Ε͹ɺͦͷ໭Γ஋ͱͯ͠ਪ࿦͞ΕΔܕ͕3ʹ֨ ೲ͞ΕΔ type Return<T> = T extends (...args:

    any[]) => infer R ? R : never; let r: Return<() => number>; // typeof r = number
  41. 3FEVYͬΆ͍ΞϨ type Return<T> = T extends (...args: any[]) => infer

    R ? R : never; type AppState<T> = { [P in keyof T]: Return<T[P]> }; const reducers = { name: (state: string, action: any) => state, age: (state: number, action: any) => state, }; let appState: AppState<typeof reducers>; // typeof appState = { name: sting, age: number }
  42. ࢖͍͗͢ʹ஫ҙ w $POEJUJPOBM5ZQFTͱ5ZQF*OGFSFODF SZʹΑͬͯɺطଘ ͷܕఆ͔ٛΒ৽͘͠ܕΛ࡞Δखஈ͕֨ஈʹ޲্ w ॻ͍ͯΔͱ͖͸ύζϧײ֮Ͱָ͍͠΋ͷͷɺద౓ͳ༻๏ɾ ༰ྔΛ৺͕͚ͨ΄͏͕Α͍ w Τϥʔϝοηʔδ͕ͲΜͲΜಡΈͮΒ͘ͳΔ

    w ϨϏϡΞ͕ͨ·ͬͨ΋Μ͡Όͳ͍
  43. VOLOPXO

  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");
  45. 5VQMFTJOSFTUQBSBNFUFST BOETQSFBEFYQSFTTJPOT

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

    w 0QUJPOBMFMFNFOUTJOUVQMFUZQFT w 3FTUFMFNFOUTJOUVQMFUZQFT
  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 }
  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);
  49. (FOFSJDSFTUQBSBNFUFST w 3FTU1BSBNFUFSTʹ૯শܕ͕ར༻Մೳʹ w +BWB4DSJQUGVODUJPOͷCJOEDBMMBQQMZͱͷ਌࿨ੑ޲্
 ޙड़ͷTUSJDU#JOE$BMM"QQMZͷૅ declare function curry<T, U

    extends any[], R>( 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
  50. 0QUJPOBMFMFNFOUTJOUVQMF UZQFT w 5VQMF5ZQFͷதͰ NPEJpFS͕ར༻Մೳʹ w 3FTU1BSBNFUFSTΛ5VQMF5ZQFͰड͚ΕΔΑ͏ͳͬͨ͜ ͱʹΑΔ෭࢈෺ type Tuple

    = [number, string?]; const x1: Tuple = [1]; const x2: Tuple = [1, "foo"];
  51. 3FTUFMFNFOUTJOUVQMF UZQFT w 5VQMF5ZQFதʹ3FTUͳUZQFΛදݱͰ͖ΔΑ͏ʹͳͬͨ w ؔ਺ͷ3FTU1BSBNFUFSTͱͯ͠΋ར༻Մೳ function hoge<T extends any[]>(...args:

    T) { return args; } const arr = [1, 2, 3]; const v = hoge("hoge", ...arr); // typeof v = [string, ...number[]] type Hoge = [string, ...number[]];
  52. .BQQFEUVQMFUZQFT

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

  54. Y type Box<V> = { value: V }; type Boxing<T>=

    { [P in keyof T]: Box<T[P]>; }; type User = { name: string, age: number, }; const boxedUser: Boxing<User> = { name: { value: "quramy" }, age: { value: 18 }, }; let boxedNumbers: Boxing<number[]>; boxedNumbers.concat.value([]); // ??? boxedNumbers.length.value; // ???
  55. Y w LFZPGOVNCFS<>ͷҙຯ͕มΘͬͨΘ͚Ͱ͸ͳ͍఺ʹ஫ҙ type Box<V> = { value: V };

    type Boxing<T>= { [P in keyof T]: Box<T[P]>; }; const boxedNumbers: Boxing<number[]> = [ { value: 1 }, { value: 100 }, ];
  56. ࢖͍Έͪ w $POEJUJPOBMUZQF (FOFSJDSFTUQBSBNFUFST .BQQFE UVQMFUZQFͷ߹ΘٕͤͷྫΛ঺հ w ͓୊SYKTͷDPNCJOF-BUFTUؔ਺ʢ˞1SPNJTFBMMతͳౕʣ interface Observable<T>

    { subscribe(cb: (v: T) => void): void; } declare var s1$: Observable<string>; declare var s2$: Observable<number>; combineLatest(s1$, s2$).subscribe(([s1, s2]) => { console.log(s1); // typeof s1 = string console.log(s2); // typeof s2 = number });
  57. ࢖͍Έͪ interface Observable<T> { subscribe(cb: (v: T) => void): void;

    } // Inference in conditional type type StreamType<T> = T extends Observable<infer S> ? S : never; // Mapped tuple type type Unboxing<U extends Observable<any>[]> = { [P in keyof U]: StreamType<U[P]>; }; // Generic rest parameters declare function combineLatest<U extends Observable<any>[]> (...args: U): Observable<Unboxing<U>>;
  58. TUSJDU#JOE$BMM"QQMZ

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

  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
  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
  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
  63. )JHIFSPSEFSGVODUJPO UZQFJOGFSFODF

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

  65. ͜͏͍͏͜ͱΒ͍͠ declare function pipe<A extends any[], B, C>( ab: (...args:

    A) => B, bc: (b: B) => C ): (...args: A) => C; declare function list<T>(a: T): T[]; declare function box<V>(x: V): { value: V }; const listBox = pipe(list, box); // <T>(a: T) => { value: T[] } const boxList = pipe(box, list); // <V>(x: V) => { value: V }[] const x1 = listBox(42); // { value: number[] } const x2 = boxList("hello"); // { value: string }[] w ैདྷ͸ɺMJTU#PY͸(a: any) => { value: any[] } ʹͳͬ ͯ͠·ͬͨ
  66. ࠓߋײ͋Δ΍ͭ import { ComponentType } from "react"; type HoC<P1, P2>

    = (c: ComponentType<P1>) => ComponentType<P2>; declare function compose<P1, P2, P3>( hoc1: HoC<P1, P2>, hoc2: HoC<P2, P3>, ): (c: ComponentType<P1>) => ComponentType<P3>;
  67. import { ComponentType } from "react"; type $Diff<T, U> =

    { [P in Exclude<keyof T, keyof U>]: T[P] }; // HoCs declare function connect<P extends {}>(c: ComponentType<P>): ComponentType<$Diff<P, { count: number }>>; declare function withRouter<P extends {}>(c: ComponentType<P>): ComponentType<$Diff<P, { location: Location }>>; 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 = () => <MyContainer className="app" />; // Outer Props͕ਪ࿦͞ΕΔ
  68. ͜͜೥ͷ৽ػೳ
 -BOHBHF4FSWJDFฤ

  69. -BOHVBHF4FSWJDF

  70. 0SHBOJ[F*NQPSU

  71. 0SHBOJ[F*NQPSU w WYͰಋೖ w UTTFSWFS -BOHVBHF4FSWJDF ʹPSHBOJ[F*NQPSUίϚϯ υ͕௥Ճ͞Εͨ w UTMJOUͷOPVOVTFEWBSJBCMFT

    JNQPSU ͷpY૬౰΋΍ͬͯ͘ ΕΔ
  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();
  73. $PEF'JY4VHHFTUJPO

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

  75. &SSPS$PEFpY w UTTFSWFS -BOHVBHF4FSWJDF ʹ͓͚ΔΤϥʔpYͷྲྀΕ  HFU4VQQPSUFE$PEF'JYFTίϚϯυͰ-BOH4FSWJDF͕ରԠՄೳͳ ΤϥʔίʔυͷҰཡΛऔಘ͓ͯ͘͠  HFU&SSPSίϚϯυͰϑΝΠϧͷΤϥʔΛ-BOH4FSWJDF΁໰͍߹Θ

    ͤΔ  $PEF'JYαϙʔτର৅ͷΤϥʔίʔυͷ৔߹ɺHFU$PEF'JYFTίϚ ϯυͰमਖ਼಺༰Λ-BOH4FSWJDFʹ໰͍߹ΘͤΔ  ड͚औͬͨมߋ಺༰ 5FYU$IBOHF ΛΤσΟλͷόοϑΝʹద༻͢Δ
  76. 4VHHFTUJPO&SSPS w ཁ͢ΔʹΤϥʔ͕ແ͍ͱɺ$PEF'JY͸Ͱ͖ͳ͍ w ʮ5ZQF4DSJQUͦͷ΋ͷ͕ਪ঑͢Δॻ͖ํʯʹϦϑΝΫλ͞ ͤΔͨΊʹ͸ɺରԠ͢ΔΤϥʔίʔυ͕ඞཁ w Α͠ɺ৽͍͠ΧςΰϦΛ࡞Ζ͏ʂͱ͍͏͜ͱͰɺ 4VHHFTUJPO&SSPS͕WYͰੜ·Εͨ

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

  78. 3FOBNFJNQPSU EFDMBSBUJPO

  79. 3FOBNFJNQPSU EFDMBSBUJPO w WYͰಋೖ w *NQPSUGSPNͷର৅෦෼ΛSFOBNFͰ͖ΔΑ͏ʹͳͬͨ /* fuga.ts */ export

    function fuga() { return "hoge"; } /* main.ts */ import { fuga } from "./fuga"; console.log(hoge());
  80. 4VNNBSZ

  81. 4VNNBSZ w $POEJUJPOBMUZQFͱ*OGFSFODF͸௒ڧྗ w 3FTUQBSBNFUFSTपΓͷվળ͕ҰؾʹਐΜͩ
 CJOEDBMMBQQMZͷܕνΣοΫ͸਱ʹདྷ͔ͨʂײ͋Δ w $PEF'JY΍ϦϑΝΫλؔ࿈΋Ҿ͖ଓ͖֦ॆ͕ਐΜͰ͍Δ

  82. &OKPZUZQJOH 5ZQF4DSJQU

  83. 5IBOLZPV