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

TypeScript Evolution

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

TypeScript Evolution

For html5 Conference 2018

Avatar for Yosuke Kurami

Yosuke Kurami

November 24, 2018
Tweet

More Decks by Yosuke Kurami

Other Decks in Programming

Transcript

  1. ܕνΣοΫͱਪ࿦ 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'));
  2. 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"));
  3. ༨ஊ /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
  4. 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 }
  5. 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>
  6. 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] };
  7. 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 }> = { };
  8. -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]; };
  9. %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"
  10. %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" };
  11. *OGFSBOE$BQUVSF w 5͕ؔ਺Ͱ͋Ε͹ɺͦͷ໭Γ஋ͱͯ͠ਪ࿦͞ΕΔܕ͕3ʹ֨ ೲ͞ΕΔ type Return<T> = T extends (...args:

    any[]) => infer R ? R : never; let r: Return<() => number>; // typeof r = number
  12. 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 }
  13. 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 }
  14. 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);
  15. (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
  16. 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[]];
  17. 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; // ???
  18. 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 }, ];
  19. ࢖͍Έͪ 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 });
  20. ࢖͍Έͪ 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>>;
  21. 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
  22. 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
  23. 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
  24. %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();
  25. &SSPS$PEFpY w UTTFSWFS -BOHVBHF4FSWJDF ʹ͓͚ΔΤϥʔpYͷྲྀΕ  HFU4VQQPSUFE$PEF'JYFTίϚϯυͰ-BOH4FSWJDF͕ରԠՄೳͳ ΤϥʔίʔυͷҰཡΛऔಘ͓ͯ͘͠  HFU&SSPSίϚϯυͰϑΝΠϧͷΤϥʔΛ-BOH4FSWJDF΁໰͍߹Θ

    ͤΔ  $PEF'JYαϙʔτର৅ͷΤϥʔίʔυͷ৔߹ɺHFU$PEF'JYFTίϚ ϯυͰमਖ਼಺༰Λ-BOH4FSWJDFʹ໰͍߹ΘͤΔ  ड͚औͬͨมߋ಺༰ 5FYU$IBOHF ΛΤσΟλͷόοϑΝʹద༻͢Δ
  26. 3FOBNFJNQPSU EFDMBSBUJPO w WYͰಋೖ w *NQPSUGSPNͷର৅෦෼ΛSFOBNFͰ͖ΔΑ͏ʹͳͬͨ /* fuga.ts */ export

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