typeof, keyof, inの動作確認

「typeof演算子」「keyof演算子」「in演算子」について取り上げます。javascriptにも存在する演算子、typescriptのみに存在する利用方法などあるので各利用方法を確認します。

typeof演算子

式で利用
( javascriptにも存在する利用方法 )

javascriptにも存在する演算子で、変数の型を取得できます。

type Person = {
  name: string;
  old: number;
};

const person: Person = {
  name: 'yamada',
  old: 22,
};

console.log(typeof ''); // string
console.log(typeof person); // object

型コンテキストで利用

756-typescript-in-typeof-keyof_00.png

型コンテキストで利用しています。変数から型を抽出しています。

画像では、型にxxxプロパティが存在しないのでエラーとなっています。

keyof演算子

型コンテキストで利用

型コンテキストで keyof を利用するとオブジェクトのプロパティ名を抽出して 文字列リテラルのユニオン型(String Literal Union) を取得できます。

type Person = {
  name: string;
  old: number;
};

type Keys = keyof Person; // "name" | "old"

let keys: Keys;
keys = 'name'; // OK
keys = 'old'; // OK
keys = 'xxx'; // Error: Type '"xxx"' is not assignable to type '"name" | "old"'.

in演算子

式で利用
( javascriptにも存在する利用方法 )

以下のように、オブジェクトのプロパティ存在有無を判定するのに利用できます。

type Person = {
  name: string;
  old: number;
};

const person: Person = {
  name: 'yamada',
  old: 22,
};

console.log('name' in person); // true
console.log('xxx' in person); // false

以下のようにforとともに利用して、プロパティを全て処理するのに利用できます。

type Person = {
  name: string;
  old: number;
};

const person: Person = {
  name: 'yamada',
  old: 22,
};

for (const prop in person) {
  console.log(prop);
}
name
old

型コンテキストで利用
( Mapped types )

まずは in演算子 を利用しない形での実装です。

type Flags = {
  x: boolean;
  y: boolean;
};

const flag: Flags = {
  x: true,
  y: false,
};

型コンテキストで in演算子 を利用すると以下のように記述できます。

type Keys = 'x' | 'y';
type Flags = { [K in Keys]: boolean };

const flag: Flags = {
  x: true,
  y: false,
};

[K in Keys] のように、Keysに 文字列リテラルのユニオン型 を指定することで同様の処理を実装しています。

先述した keyof演算子文字列リテラルのユニオン型 を取得できるので、以下のように活用することができます。

type Flags = {
  x: boolean;
  y: boolean;
};
type PartialFlags = { [K in keyof Flags]?: Flags[K] };

// Error: Property 'y' is missing in type '{ x: true; }' but required in type 'Flags'.
const flag1: Flags = {
  x: true,
};

// OK
const flag2: PartialFlags = {
  x: true,
};

プロパティを省略可能な型に変更しました。

参考