TypeScript学習 Day 2: 関数とUnion型 / Intersection型

概要

Claudeにちゃんと書いてこなかった言語のカリキュラムをつくってもらって学習している。

TypeScript学習カリキュラム Day 2。関数の型アノテーション、Union型・Intersection型、never型による網羅性チェックを学習した。

今日学んだこと

※一部Day1の内容が混ざっている

関数の型アノテーション

  • 基本の function 宣言とアロー関数(=>)の2パターン
  • オプショナル引数(?)とデフォルト値
  • Null合体演算子(??): Rubyの || に近いが、nullundefined だけを判定する

Union型の深掘り

  • リテラル型のUnion(type Status = "pending" | "in_progress" | "done")で、決まった値だけを許容する型が作れる
  • Rubyのシンボル的な使い方に近い

Intersection型(&)

  • 複数の型を合体させる(type Person = Name & Age
  • Rubyの Hash#merge のイメージ

never型と網羅性チェック

  • never は「ここには絶対来ないはず」を表す型
  • switchdefaultnever に代入することで、case の追加漏れをコンパイルエラーで検出できる
  • Rubyの raise のコンパイル時版のようなもの
  • _exhaustive: neverreturn すれば、never は全ての型の部分型なので戻り値の型エラーにならない

実践課題

formatValue(value: string | number | boolean): string を実装。

  • string"文字列: hello"
  • number → 小数点2桁にして "数値: 3.14".toFixed(2)
  • boolean"真偽値: はい" / "真偽値: いいえ"
  • typeof による型ガードで分岐
  • never による網羅性チェック

結果: 課題クリア!型ガードと網羅性チェックを正しく実装できた。

質問と回答

Q: Union型はRubyにない概念?一つの変数で複数の型を許容できる?

その通り。Rubyは動的型付けなので何でも入るが、TSは|で明示的に許容する型を宣言する。

Q: null / undefinedはRubyでいうとnilと変数未定義?

ほぼ合っている。null = Ruby の nil(意図的に「値がない」)、undefined = 変数が未定義・プロパティが省略された状態。

Q: 型ガードはどう実現されている?

実行時に何か特別なことをしているわけではなく、TSコンパイラが if 文を静的解析して型を絞り込んでいる。コンパイル後のJSには型情報は一切残らない。

Q: neverのdefaultで何をreturnすればいい?

const _exhaustive: never = value; return _exhaustive; とすればOK。never は全ての型の部分型なので、string を返す関数でも型エラーにならない。

Q: 変数名の先頭の _ は慣習?

Rubyと同じで「この変数は使わないよ」という意味の慣習。TSでも未使用変数の警告を抑制できる。

Q: 独自型の命名に慣習はある?

大文字始まり(PascalCase)が慣習。StatusValue など。

メモ

  • 変数展開文字列は `${}`
  • toFixed は文字列を返す
  • switch のあとが評価式で case に値が来る
  • 三項演算子はRubyと一緒