🦔

[TypeScript]typeof型とkeyof型についてのまとめ

2024/01/17に公開

typeof型とは

typeof型は、変数やオブジェクトの型を取得する機能です。
変数やオブジェクトの実際の値ではなく、その型情報を取得する際に使います。

例①

// type ofについて
const obj = {
  foo: 123,
  bar: "hi",
};
type L = typeof obj;
const obj2 = {
  foo: 234,
  bar: "",
};

このコードでは、「typeof obj」とすることで、「obj」オブジェクトの型を取得し、「type L」に適用させています。

例②

const n: unknown = "";
 
if (typeof n === "string") {
  n.toUpperCase;
}

例③

function isObject(value) {
  return value !== null && typeof value === "object";
}

keyof型とは

keyof型は、オブジェクト型からそのオブジェクトのプロパティ名を型として取得する機能です。

例①

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

このコードは、「Person」からプロパティである「name」を取得し、「PersonKey」に反映させているコードになります。

例②

type Human = {
  name: string;
  age: number;
  height: number;
};
type HumanKey = keyof Human;
// 上は次と同じ意味になる
type BookKey = "name" | "age" | "height";

こちらも先ほどのと考え方は同じで、「Human」を指定することで、全てのプロパティを取得し、ユニオン型として適用させることができます。

例③

// key ofについて

type Human = {
  name: string;
  age: number;
};

type HumanKey = keyof Human;
let key: HumanKey = "name";
key = "age";
// 型 '"hoge"' を型 'keyof Human' に割り当てることはできません。(エラー)
// key = "hoge";

このコードでは、HumanKey型は、「keyof Human」として宣言され、Human型のプロパティ名を文字列リテラル型として取得しています。つまり、HumanKeyは「"name" | "age"」という文字列型のユニオン型です。
最後の行で、「key = "hoge";」 としていますが、これはエラーとなります。なぜなら、「"hoge"」は HumanKey 型に含まれていないため、key の型としては許容されないからです。この行がエラーになることで、型の一貫性が保たれ、予期せぬ挙動を防ぐことができます。

例④

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

「keyof」で何も指定しなかった場合、そのオブジェクトに対するキーが存在しないため、「never」型が結果となります。

例⑤

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

「keyof」で「any」型を指定した場合、その型のすべてのプロパティのキーが取得され、結果として、「string」「number」「symbol」のユニオン型が取得できます。

typeofとkeyofを合体

// typeofとkeyofを合体
const mmConversionTable = {
  mm: 1,
  m: 1e3,
  km: 1e6,
};

function convertUnits(value: number, unit: keyof typeof mmConversionTable) {
  const mmValue = value * mmConversionTable[unit];
  return {
    mm: mmValue,
    m: mmValue / 1e3,
    km: mmValue / 1e6,
  };
}

console.log(convertUnits(5600, "m"));
// 出力:

このコードは、keyofとtypeofを併用して型定義をしているコードです。

convertUnits(value: number, unit: keyof typeof mmConversionTable)

この箇所では、「value」はnumber型を定義して、数値以外を受け取れないようにしています。
「unit」では、typeofで「mmConversionTable」の各プロパティの型情報を取得し、keyofで型情報の

参考

https://typescriptbook.jp/reference/values-types-variables/typeof-operator

https://typescriptbook.jp/reference/type-reuse/keyof-type-operator

Discussion