🗝️

TypeScriptにおけるkeyofの使い方をまとめておいた

2023/09/05に公開

はじめに

TypeScriptのkeyof演算子周りがややこしすぎたのでスゲー簡単にまとめました。

keyof演算子

オブジェクトの型からプロパティ名を型として返す型演算子。

1つのプロパティを持つオブジェクトの型にKeyofを使った場合、文字列リテラル型の"name"が得られる。

type Person = {
  name: string;
}
type PersonKey = keyof Person;  // type PersonKey = "name"

2つ以上のプロパティがあるオブジェクトの型にkeyofを使った場合、全てのプロパティ名がユニオン型で返される。

type Book = {
  title: string;
  price: number;
  rating: number;
};
type BookKey = keyof Book;  // type BookKey = "title" | "price" | "rating";

インデックス型keyofを使うと、インデックスキーの型が返る。

type MapLike = {[K: string]: any};
type MapKeys = keyof MapLike; //type MapsKeys = string | number

マップ型kayofを使うと、そのキーの型が返る。

type MapLike = { [K in "x" | "y" | "z"]: any };
type MapKeys = keyof MapLike; // type MapKeys = "x" | "y" | "z";

プロパティを持たないオブジェクトの型にkeyofを使うとnever型が返る。

type What = keyof {}; // type What = never; 

any型にkeyofを使うとstring | number | symbol型が返る。

type AnyKeys = keyof any; // type AnyKeys = string | number | symbol;

出てきた型解説

ユニオン型

「いずれかの型」を表現するもの。

let numberOrUndefined: number | undefined;  // 型注釈
type ErrorCode = 
  | 400
  | 401
  | 402
  | 403
  | 404
  | 405; 
type List = (string | number)[];  // 配列型(T[])にユニオン型を使う場合   

インデックス型(インデックスシグネチャ)

オブジェクトのフィールド名を指定する必要がない型。

let obj: {
  [K: string]: number;
};

obj = {a: 1, b: 2};
obj.c = 4;
obj["d"] = 5; 

マップ型

ある型をもとに新たな型を定義する際に利用される型のこと。主にユニオン型、インデックス型、in演算子を組み合わせて使う。

type Fig = 'one' | 'two' | 'three';
type FigMap = {
  [K in Fig]: number
};

const figmap: FigMap = {
  one: 1,
  two: 2,
  three: 3,,
};
figMap.four = 4;  // コンパイルエラー

ユニオン型Figとインデックス型とin演算子を組み合わせることで、キーの値を限定する新しい型FigMapを作り出した。この型がマップ型である。

参考:

Discussion