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

TypeScriptってどんな言語? 言語そのものを知る面白さ

uhyo
November 08, 2023

TypeScriptってどんな言語? 言語そのものを知る面白さ

2023年11月8日
プロを目指す人のためのTypeScript入門 - Forkwell Library #35

uhyo

November 08, 2023
Tweet

More Decks by uhyo

Other Decks in Programming

Transcript

  1. 3章 オブジェクトの基本とオブジェクトの型 オブジェクトの概念と、オブジェクトに関連した構文を学ぶ。 3章ではデータ構造としてのオブジェクトを扱い、 普通のオブジェクト( { } )と配列( [ ]

    )を学ぶ。 オブジェクトの型の表し方も一緒に学習する。 ジェネリック型 Foo<T> もここで導入。 🫐 一押しポイント: オブジェクトに対する === の判定 や 部分型関係などの 込み入った話題も解説し、曖昧な点を後に残さない構成に。 (広く浅く進んでいくよりは、単元ごとにしっかり深入りする教科書っぽい構成を意識)
  2. TypeScriptの面白いところ 特にTypeScriptはタグ付きユニオンのサポートが手厚い。 (「タグ」を見れば判別できるユニオン型をタグ付きユニオンと言う) type OperationResult<T> = | { success: true;

    data: T } | { success: false; error: unknown } // この場合はsuccessプロパティがタグ if (result.success) { // success: true の場合に絞り込まれる console.log(result.data); } else { // success: false の場合に絞り込まれる console.error(result.error); }
  3. 論理和を論理積で表現しない ユニオン型を知らないと、次のように表現しがち。 type OperationResult<T> = | { success: true; data:

    T } | { success: false; error: unknown } // よくない表現 type OperationResult<T> = { success: boolean; data?: T; error?: unknown; }
  4. 論理和を論理積で表現しない なぜ良くないのか? →設計上意図しない値が混ざるから // 意図した値 { success: true, data: “pikachu” }

    { success: false, error: new Error(...) } // 意図していない値 { success: true, error: new Error(...) } { success: false, data: “pichu” } { success: true } { success: true, data: “pikachu”, error: new Error(...) } // よくない表現 type OperationResult<T> = { success: boolean; data?: T; error?: unknown; }
  5. 論理和を論理積で表現しない 論理和のほうが、論理積より正確に可能性を表現できる。 // 論理和 type OperationResult<T> = | { success:

    true; data: T } | { success: false; error: unknown } // 論理積 type OperationResult<T> = { success: boolean; data?: T; error?: unknown; } 1 + 1 = 2 成功: 1通り 失敗: 1通り 2 × 2 × 2 = 8 success: 2通り(true / false) data: 2通り(ある / 無い) error: 2通り(ある / 無い)
  6. 正確に可能性を表現する利点 種類の判別方法を「タグを見る」に強制できるので、バグりにくい。 type OperationResult<T> = | { success: true; data:

    T } | { success: false; error: unknown } // タグを見ないと絞り込めない! if (result.success) { console.log(result.data); } else { console.error(result.error); } type OperationResult<T> = { success: boolean; data?: T; error?: unknown; } // いろいろなやり方ができてしまう…… if (result.success) { … } if (result.data) { … } if (!result.error) { … }
  7. 正確に可能性を表現する利点 種類の判別方法を「タグを見る」に強制できるので、バグりにくい。 これは正常系で data に number が入 る仕様だと0のときバグるぞ! type OperationResult<T>

    = { success: boolean; data?: T; error?: unknown; } // いろいろなやり方ができてしまう…… if (result.success) { … } if (result.data) { … } if (!result.error) { … }
  8. 例: クイズ // data: string const prefix = data.slice(0, prefixLength);

    これまでprefixLengthがany型だったため型エラーが起きていませんでしたが、 prefixLengthの型を直したら実はstring型だったため型エラーが起きました。 しかし何かランタイムでは動いているようでした。 動作を変えずに型エラーを消すために、 data.slice(0, Number(prefixLength)) と変えても良いでしょうか?
  9. 例: クイズ // data: string const prefix = data.slice(0, prefixLength);

    const prefix = data.slice(0, Number(prefixLength)) 答え: 変えていい JavaScriptの仕様書を参照すると、String.prototype.sliceに文字列が渡された場合に はToNumberで数値に変換されることになっている。 一方、自分でNumberを呼び出すのも結局内部的にはToNumberに行き着くため、どち らでも同じ処理になるため動作が変わらない。
  10. 例: クイズ // data: string const prefix = data.slice(0, prefixLength);

    const prefix = data.slice(0, Number(prefixLength)) 仕様書が読めれば、このような変更を、根拠を持って行うことができる。 🫐 この本だけでは仕様を読みに行けるところまでは到達しないが、仕様書の紹介はしているし基礎固めにな   るはず……
  11. 技術の進化の例① Stage 2 Proposal: throw expression https://github.com/tc39/proposal-throw-expressions 最近rbucktonさん(TypeScriptチーム)によって進められているプロポーザル。 🫐 プロポーザル:

    JavaScriptの新機能。仕様がまとまるとステージが上がり、 3で内定、4で正式採用となる コード例(引用): function getEncoder(encoding) { const encoder = encoding === "utf8" ? new UTF8Encoder() : encoding === "utf16le" ? new UTF16Encoder(false) : encoding === "utf16be" ? new UTF16Encoder(true) : throw new Error("Unsupported encoding"); }
  12. 技術の進化の例① function getEncoder(encoding) { const encoder = encoding === "utf8"

    ? new UTF8Encoder() : encoding === "utf16le" ? new UTF16Encoder(false) : encoding === "utf16be" ? new UTF16Encoder(true) : throw new Error("Unsupported encoding"); } 基礎知識が薄い人の反応例 「throwってエラー発生させるやつだよね? こ れは何が新しいの?  でも何か違和感があるような」 基礎知識がしっかりした人の反応例 「なるほど、既存のthrowは文だけどこれは  新しくthrowを式として使える提案なのか」 🫐 文と式という概念を知っているため、どこが既存機能 との差分なのか理解できる。 用 語 を 知 っているためプロポーザル 名 から 内 容 を 推測できる。
  13. 技術の進化の例② const { promise, resolve, reject } = Promise.withResolvers(); 基礎知識が薄い人の反応例

    「あーPromiseは非同期処理のやつね。  もちろん知ってるけどpromiseと一緒に 返さ れてるresolveとrejectって何?」 基礎知識がしっかりした人の反応例 「Promiseの静的メソッドってことはPromiseを  新しく作る関数だな。resolveとrejectは  new Promiseでコールバックに渡される関数を 取り 出せる感じかな?」 🫐 Promiseの動作機序やnew Promiseのシグネチャを   基礎知識として知っており活用できるため、   Promise.withResolversの機能・利便性も   想像できる。
  14. 発売当時のバージョンと今のバージョン 発売当時のバージョン: TypeScript 4.6 (2022年2月リリース) 現在のバージョン:   TypeScript 5.3(2023年8月リリース) 🫐 裏話:

    本が4月発売なので、同年2月(しかも28日)リリースのバージョンに対応するのはけっこう粘っている。 スナップショットテスト的な仕組みを用意して本に登場するコード片の結果が最新の TypeScriptバージョンでも変わらないこ と を担保した。
  15. TypeScript 4.7の主な変化 .ctsと.mtsの導入、mode: “node16” の追加など、 Node.jsのCJS/ESM両対応機能にTypeScript側も対応した。 🫐 本ではNode.jsでサンプルコードを動かすから正直これは発売前に欲しかった 型引数に変性パラメータ(in, out)を書ける機能が追加された。

    🫐 けっこう難しい機能だが、本書を読んで   共変・反変について理解していれば大丈夫。   これもあったほうが説明が楽だったかも type Getter<out T> = () => T; type Setter<in T> = (value: T) => void; interface State<in out T> { get: () => T; set: (value: T) => void; } https://devblogs.microsoft.com/typescript/announcing-ty pescript-4-7/ より引用
  16. TypeScript 4.8の主な変化 unknown と {} | null | undefined の相互運用性が強化された。

    事実上 {} は「nullとundefined以外全部」という意味の型だったが、 その性質がより明確になり、さらに一貫性が増して嬉しい。 // something: unknown if (something !== null) { // something: {} | undefined } 🫐 これもあったほうが説明しやすいので欲しかった(毎回言ってる)
  17. TypeScript 4.9の主な変化 satisfies構文が追加された。 地味に効能が分かりにくい構文だが、基本用語や型推論の機序を知っていれば 理解しやすい! 式 satisfies 型 (式 satisfies

    型)の型は式の型推論結果と変わらない。 ただし、式の型推論時にContextual Typeとして型が用いられる。 また、式の型推論結果が型の部分型であることもチェックされる。
  18. TypeScript 5.2の主な変化 using宣言のサポートが大きい。 var, let, constに次ぐ第四の変数宣言である。 🫐 解説を本に入れるとしたらどの章に入れるかすごく迷いそう 右のコードは、関数を出たら 一時ファイルが自動的に削除

    される。 try-finallyの発展と考えると 理解しやすい。 export function doSomeWork() { using file = new TempFile(".some_temp_file"); // use file... if (someCondition()) { // do some more work... return; } } https://devblogs.microsoft.com/typescript/announcing-typescript-5-2/ より引用