公開日: 2023/05/14 @Miz_dev
型の絞り込み。
型が複数考えられる場合に Type Guard で型を特定していくこと。
以下のように、typeof 用いることで型の絞り込みが出来る。
export const foo = (value: string | number | boolean) => {
if (typeof value === "string") {
return value;
// value: string
}
if (typeof value === "number") {
return value;
// value: number
}
return value;
// value: boolean
};
Array.isArray()のような JavaScript のメソッドを用いて、型の絞り込みが出来る。
export const foo = (value: string | string[]) => {
if (Array.isArray(value)) {
return value;
// value: string[]
}
return value;
// value: string
};
例えば以下のように論理否定演算子を用いて、value が falsy だった場合に if 文の中を返すことで、undefined の可能性を消去できる。
export const foo = (value?: string) => {
if (!value) {
return value;
// value: string | undefined
}
return value;
// value: string
};
こちらは頻出で、React 等を使っていて上から props が渡ってきた時に props の値がオプショナルだった場合に可能性を消去する。
そして、下の return 文でコンポーネントを記述する。のような場面で出てくる。
ちなみに、if 文内はvalue: string | undefined
となっているが、空文字に!を付けるとtruthy となる=条件分岐に入り string の可能性が残るということ。
実際は以下のように、null やただの return にする。
export const foo = (value?: string) => {
if (!value) {
return null;
}
return value;
};
or
export const foo = (value?: string) => {
if (!value) {
return;
}
return value;
};
以下のように”nickname” in value
とすることで、value に nickname があるかどうかで、型の絞り込みが出来る。
type UserA = { name: string };
type UserB = { name: string; nickname: string };
export const foo = (value: UserA | UserB) => {
if ("nickname" in value) {
return value;
// value: UserB
}
return value;
// value: UserA
};
以下のように UserA も UserB も同じようなプロパティを持っている時に、タグ付き Union Types を用いて型の絞り込みが出来る。
type UserA = { name: string; lang: "ja" };
type UserB = { name: string; lang: "en" };
export const foo = (value: UserA | UserB) => {
if (value.lang === "ja") {
return value;
// value: UserA
}
return value;
// value: UserB
};
実際には Admin と一般ユーザーを分けたりするような type,kind,id 等をよく見るが特に決まりはなく、色々なプロパティが Tag として使われる。
以下のように、switch 文を用いて型の絞り込みが出来る。
type UserA = { name: string; lang: "ja" };
type UserB = { name: string; lang: "en" };
type UserC = { name: string; lang: "fr" };
export const foo = (value: UserA | UserB | UserC) => {
switch (value.lang) {
case "ja": {
return value;
}
case "en": {
return value;
}
case "fr": {
return value;
}
default: {
throw Error("lang is not defined!");
}
}
};