0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TypeScriptのkeyof typeof周りを整理した

Posted at

型定義でkeyof, typeof、またkeyofとtypeofが混ざって使われるケースを整理してみました。

keyof

オブジェクトの型からプロパティ名(key名)を型として返す型演算子です。
2つ以上のプロパティがあるオブジェクトの型にkeyofを使った場合は、すべてのプロパティ名がユニオン型で返されます。

以下のサンプルで、オブジェクトのキーが文字列リテラルのユニオン型を生成できる。
自分で定義しても同じですが、この方法を使うのが一般的です。

type Hoge = {
  name: string;
  age: number;
  gender: string;
}

// Hogeのキーである'name' | 'age' | 'gender'の文字列リテラルのユニオン型が生成される
type SampleType = keyof Hoge

const data1: SampleType = "age" // OK
const data2: SampleType = "job" // NG (name, age, gender以外はエラーになる)

// 生成したユニオン型に別の文字列を追加して汎用的に使い回す
type SampleTypeWithJob = keyof Hoge | "job"
const data3: SampleTypeWithJob = "job" // OK

// 生成したユニオン型から不要な値を除去して使う
type SampleTypeWithoutAge = Exclude<SampleType, 'age'>
const data4: SampleTypeWithJob = "age" // NG

typeof

typeof 演算子は対象の値のデータ型を表す文字列を返す演算子。
データ型を調べることができます。

const hogeStr = "hogehoge"
// typeof hogeStr を実行すると、'string' が返される

const hogeNum = 1234
// typeof hogeNum を実行すると、'number'が返される

以下は型定義でよくあるユースケース

// 配列データ
const size = ['small', 'medium', 'large'] as const

// 'small' | 'medium' | 'large'の文字列リテラルのユニオン型が生成される
type Size = typeof size[number]

const a = 'small' // OK
const b = 'extraLarge' // NG!!

// オブジェクトの配列
const RANK_NAME_POINTS = [
  { rank: 'bronze', point: 0 },
  { rank: 'silver', point: 1500 },
  { rank: 'gold', point: 3200 },
] as const

// "bronze" | "silver" | "gold" の文字列リテラルのユニオン型が生成される
type RankNameType = typeof MEMBERS_RANK_NAME_POINTS[number]['rank']

// これに別の文字列を足すことも勿論可能
type MembersRankNameType2 = typeof MEMBERS_RANK_NAME_POINTS[number]['rank'] | 'free'

keyofとtypeofを混合で使うケース

これもよく見かけますが、紐解いてみると仕組みは簡単です。

const hoge = {
  name: "Taro Yamada",
  age: 30,
  gender: "male"
}
// typeofでobjの型が取れる
type SampleType1 = typeof hoge
// これと同じ
type SampleType1 = {
  name: string;
  age: number;
  gender: string;
}

// そのobjの型のkeyを取り出してユニオン型を生成 "name" | "age" | "gender"
type SampleType2 = keyof typeof hoge
// objのvalueをユニオン型にする場合 as constが必要
const objData = {
  groupName: 'グループ名',
  storeName: '店舗名',
  address: '住所',
} as const

// "グループ名" | "店舗名" | "住所" のユニオン型ができる
type ObjDataValues = typeof objData[keyof typeof objData]
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?