Slide 1

Slide 1 text

TypeScript の型とお作法 手強いコードベースと向き合ってきた 僕のお気持ち 2024 春 2024/05/11 札幌ITでぃぐでぃぐ会 vol.1 ~TypeScript 勉強会~ 渡辺隼人

Slide 2

Slide 2 text

自己紹介 • 渡辺隼人 • 株式会社サーバーワークス • 札幌在住 (2023/7 ~) • any 撲滅委員会として活動中 • X: @nabecmdctrl

Slide 3

Slide 3 text

はじめに • TypeScript はスーパーセットということを覚えておこう • コンパイラはだませる • 過去 1 年間で 350 件ほど PR レビューを実施した者の話です • コードは必ずしもコピペで問題なく動くもモノではないです • 今日の話は僕の考える最強の~系なので参考程度にどうぞ • まさかり待ってます

Slide 4

Slide 4 text

本日のお品書き • object を typeof 演算子で評価するのは 気を付けて • Array.filter に気を付ける • 型ガード • Input の型 • any 撲滅委員会 • 純関数委員会 • 配列を index で操作するのは避けたい • Truthy, Falsy の評価に気を付けよう • Union 混ぜるな危険 • eslint-disable はライン指定 • Array.map forEach を使い分ける • as unknown as で上書き • 配列は空配列で初期化するとよい • 不要なオプショナルアクセス演算子を 削除したい • NaN で? • Utility Type を使おう • null と undefined を同時に check • 型宣言 • Wrapper Library で型が提供されていない 場合もあきらめない

Slide 5

Slide 5 text

object を typeof 演算子で評価するのは気を付けて • 配列や null も object Why • typeof - JavaScript | MDN 私のお気持ち • どちらかを使いましょう • type predicates • Zod

Slide 6

Slide 6 text

Array.filter に気を付ける • 型推論されません Why • コンパイラおバカ • Infer type predicates from function bodies using control flow analysis お気持ち • TypeScript はスーパーセット だね

Slide 7

Slide 7 text

型ガード • 型を判別しましょう Why • 型を確定させないと意図し ているプロパティにアクセ スできない お気持ち • in 演算子とかでむりくり型 推論するのやめてくれ

Slide 8

Slide 8 text

any 撲滅委員会 • any は型という概念を消す Why • 型がみえないよ~ • TypeScript 使っている意味を 考えたい お気持ち • no-explicit-any • unknown を使う

Slide 9

Slide 9 text

純関数委員会 • プリミティブ以外は参照渡 しになっちゃう Why • プログラムの原則でもある • 副作用は避けたい お気持ち • no-param-reassign

Slide 10

Slide 10 text

配列を index で操作するのは避けたい • index 操作だと配列の範囲を 考慮した型推論がされない Why • なんで? お気持ち • オブジェクトに • したらいいよね

Slide 11

Slide 11 text

Truthy, Falsy の評価に気を付けよう • Truthly, Falsy な値を評価をす ると。。 Why • 言語的にそうなんすね。 きっと お気持ち • strict-boolean-expressions

Slide 12

Slide 12 text

Union 混ぜるな危険 • Union で型定義すると何が何 だかわからない Why • どっちの型かわからないの。 お気持ち • Generics 使おう

Slide 13

Slide 13 text

eslint-disable はライン指定 • // eslint-disable-next-line をつかおう! Why • ファイル指定にすると他の lint 警告・エラーを見落とし ます。 お気持ち • 同上

Slide 14

Slide 14 text

Array.map forEach を使い分ける • Array.map: 元の配列を変換し、 変換後の新しい配列を返す • Array.forEach: 各要素に対し て順番に関数を実行し、そ の関数による副作用をもた らす。 Why • 言語が提供している機能の 目的に沿って記述したい お気持ち • 可読性を意識すると選択す べきメソッドがわかるはず

Slide 15

Slide 15 text

as unknown as で上書き • どうしても型があわないと きで動作が担保できるケー スはあり! Why • コンパイラはだませる! お気持ち • ランタイムと合わせるなら ありだと思う

Slide 16

Slide 16 text

配列は空配列で初期化するとよい • nullish を排除する Why • Iteration protocols に準拠し たものとして扱える お気持ち • 型チェック挟むより良い場 合がある

Slide 17

Slide 17 text

不要なオプショナルアクセス演算子を削除したい • 運用が進んでいくとゴミが 残る可能性があります Why • 精神衛生の向上 お気持ち • no-unnecessary-condition

Slide 18

Slide 18 text

NaN で? • NaN は number 型 • しっかりチェックしないと いけない • あと NaN マイルで undefined 会員は避けたい Why • 言語設計かな? • なんでだろう お気持ち • NaN が number でこういう時 いいよねってあれば教えて ください

Slide 19

Slide 19 text

Utility Type を使おう • Utility Type を使うと既存の 型からいろいろできます。 お気持ち • (広義の) 定義が存在するの であれば独自定義をする必 要はない

Slide 20

Slide 20 text

null と undefined を同時に check • 等価演算子でいいよ Why • TypeScript Deep Dive で言っ てるから お気持ち • それ以外は厳密等価演算子 を使いましょう

Slide 21

Slide 21 text

型宣言 • 推論できるなら推論したい Why • 根幹の型が変わった場合、 コードの修正点が増える お気持ち • ある程度の精度がでている 推論型のケースは型を明示 させない lint 教えて

Slide 22

Slide 22 text

Wrapper Library で型が提供されていない場合もあ きらめない • ときどきあります • 例: vue.draggable は SortableJS の Wrapper です。 MoveEvent 型とかが SortableJS のほうにしかない (ような気がする) Why • そういうときもある お気持ち • ライブラリを使ってるのに 型定義自分でするのはおか しいでしょという気持ち

Slide 23

Slide 23 text

HTML Input number の value の型 • string なんすわ。。 • undefined もあるぞ。。 Why • なんで?わかんない • - HTML: HyperText Markup Language | MDN お気持ち • どうすればいいんですか? • とりあえず型全部みます

Slide 24

Slide 24 text

Thank you!