TL;DR

  • どんな文字列でも受け入れるわけではない値には、string より適切な型を選ぶ(Stringly typed を避ける)。
  • 文字列リテラル型のユニオンを使うと値のドメインを正確に表せ、オブジェクトのプロパティ名を受け取る引数には keyof T を使う。

内容

文字列リテラル型を使う

あらゆる string を受け入れるわけではない値には、より適切な型を選ぶ。文字列リテラル型を使うと、値のドメインをより正確に表せる。型チェックが厳格になるだけでなく、TSDoc を付けられたり、意図が明確になったりと、開発体験も向上する。

// NG
interface Album {
  artist: string
  title: string
  releaseDate: string
  recordingType: string
}
// OK
type RecordingType = "studio" | "live"
interface Album {
  artist: string
  title: string
  releaseDate: Date
  recordingType: RecordingType
}

プロパティ名には keyof T を使う

オブジェクトのプロパティ名であることを期待する引数には、keyof T を使う。

// NG
function pluck(records: any[], key: string): any[] {
  return records.map((r) => r[key])
}
// OK
function pluck<T, K extends keyof T>(records: T[], key: K): T[K][] {
  return records.map((r) => r[key])
}

キーワード