業務でtypeofとkeyofが出てきたので、備忘録として残しておきます。
(typescriptの型関連が難しい......)
typeofとは
typeof
を使うことで、オブジェクトや変数の型そのものが取得できます。
使用例
const person = {
name: "Alice",
age: 30,
};
// `person` と同じ構造の型を定義
type PersonType = typeof person;
const anotherPerson: PersonType = {
name: "Bob",
age: 25,
};
ポイント:
typeof person
は person
オブジェクトの型 { name: string; age: number }
を取得します。
こうすることで、person
に新しいプロパティを追加しても、PersonType
を自動的に更新できるので、変更に強いコードとなります。
keyofとは
keyof
をつかうことで、オブジェクト型のキー(プロパティ名)を文字列リテラル型として取得できます。(型のみで使用可能)
使用例
type Example = {
a: number;
b: string;
c: boolean;
};
// keyof を使用
type Keys = keyof Example;
// Keys は "a" | "b" | "c" というリテラル型
const obj: Example = { a: 1, b: "hello", c: true };
// 型安全なプロパティアクセス
const getValue = (key: Keys): Example[Keys] => obj[key];
const valueA = getValue("a"); // OK: number型
const valueB = getValue("b"); // OK: string型
// getValue("d"); // エラー: '"d"' は 'Keys' に割り当てられません
ポイント:
keyof Example
は Example
型のすべてのプロパティ名をリテラル型として取得します。
keyof
を使うと、プロパティ名以外の無効なキーにアクセスしようとするとエラーになるため、型安全な操作が可能となります。
typeof と keyof を組み合わせた場合
以下はオブジェクトのプロパティ名と値を利用した例です。
const Status = {
SUCCESS: "success",
ERROR: "error",
LOADING: "loading",
} as const;
// typeof と keyof を使って型を生成
// type StatusValue = (typeof Status)[keyof typeof Status] でも同じ
type StatusKey = keyof typeof Status; // "SUCCESS" | "ERROR" | "LOADING"
type StatusValue = (typeof Status)[StatusKey]; // "success" | "error" | "loading"
// 型安全な関数
function handleStatus(status: StatusValue) {
if (status === "success") {
console.log("Operation was successful!");
} else if (status === "error") {
console.log("An error occurred.");
} else if (status === "loading") {
console.log("Still loading...");
}
}
// 使用例
handleStatus("success"); // OK
// handleStatus("unknown"); // エラー
ポイント:
keyof typeof Status
でキーリテラル型("SUCCESS" | "ERROR" | "LOADING")を取得します。
次に、(typeof Status)[keyof typeof Status]
で値リテラル型("success" | "error" | "loading")を取得します。
as const
の補足説明
const Status = {
SUCCESS: "success",
ERROR: "error",
LOADING: "loading",
} as const;
as const
の役割:
- Status を読み取り専用(
readonly
)にする。 - 各プロパティの型を
"success"
,"error"
,"loading"
のリテラル型に変換する。
(as const
がない場合、Status のプロパティは一般的なstring
型と解釈されてしまうので、リテラル型の恩恵を受けられない。)
まとめ
-
typeof
:- 変数やオブジェクトの型を取得して再利用できる
- 型定義を重複せず、変更に強いコードが書ける
-
keyof
:- オブジェクト型のすべてのキーをリテラル型として取得する
- 型安全なプロパティアクセスが可能となる
-
typeof
とkeyof
の組み合わせ:- typeofで型を取得して、keyofでプロパティ名をリテラル型で取得することで、型安全なキーや値の操作が可能となる
使用方法はなんとなくわかったけど、実際に使いこなせるのか
実務経験をたくさん積みたい。