useStateの型
useState
の状態管理関数をProps
で渡すとき、受け取る側は
Dispatch<SetStateAction<T>>;
という方で受け取ることになる。
ジェネリクスのメリットがいまいち
関係ないけどずっと気になっていた「ジェネリクスのメリットがいまいちピンとこない件」について、ついでに調べてみることにした。
例えば、
// 文字列を入力し、文字列を出力する関数
const returnText = (input: string): string => {
return input;
};
// 数値を入力し、数値を出力する関数
const returnNumber = (input: number): number => {
return input;
};
console.log(returnText("hello world"), "returnText");
console.log(returnNumber(0), "returnNumber");
という関数が存在した時、
const returnTextOrNumber = (input: string | number): string | number => {
return input;
};
console.log(returnTextOrNumber("hello world"), "returnTextOrNumber");
console.log(returnTextOrNumber(0), "returnTextOrNumber");
こんな感じにまとめたくなる。
これをジェネリック型にすると、
const returnTextOrNumberGeneric = <T extends string | number>(input: T): T => {
return input;
};
こんな感じになる。
型ガードが必要
同じように感じるけど、returnTextOrNumber
の場合は、
const a: string | number = returnTextOrNumber("hello world");
const b: string | number = returnTextOrNumber(0);
console.log(a.length);
// Property 'length' does not exist on type 'string | number'.
// Property 'length' does not exist on type 'number'
console.log(b + 1);
// Operator '+' cannot be applied to types 'string | number' and 'number'.
string
とnumber
のどちらが返ってくる確定していないので、コンパイルエラーが出る。
実行するためには
if (typeof a === "string") {
console.log(a.length);
}
if (typeof b === "number") {
console.log(b + 1);
}
のように型ガードする必要がある。
コンパイラーをだませる
const b: string | number = returnTextOrNumber(0) as string;
console.log(b.length);
bは0なのでlength
が存在しないが、as string
で強制的に文字列とコンパイラーと認識させられる。
これはコード的負の遺産になる。
ジェネリック型は堅牢でコード量が少ない
対照的にジェネリック型であるreturnTextOrNumberGeneric
の場合は、
const a = returnTextOrNumberGeneric<string>("hello world");
const b = returnTextOrNumberGeneric<number>(0);
console.log(a.length);
console.log(b + 1);
関数実行時に入出力共に型を指定し確定できるので、コンパイルエラーがでない。
また
const b = returnTextOrNumberGeneric<number>(0) as string;
// Conversion of type 'number' to type 'string' may be a mistake because neither type sufficiently overlaps with the other. If this // was intentional, convert the expression to 'unknown' first.(2352)
強制的に異なる方でコンパイラーを納得させようとしても不可能になり、堅牢制が向上した。
実際に整理してみるとジェネリック型の恩恵がよくわかった。