nullable
な Array
を non-null
に filter
するとき
ふつうにこう書いたとして:
const nullables: (number | null)[] = [1, 2, 3, null, 4];
const nonNullables: number[] = nullables.filter(
(item: number | null) => item !== null
);
実質的には Array.prototype.filter
内で item !== null
でフィルタしているので
nonNullables
の要素はすべて non-null
であるはずですが、
Type '(number | null)[]' is not assignable to type 'number[]'.
Type 'number | null' is not assignable to type 'number'.
Type 'null' is not assignable to type 'number'.
実際のところ、filter
の返り値は依然 nullable
として扱われてしまい、
エラーになってしまいます。
Type Predicate (型述語) を使う
Type Predicate を返すような関数 (Type Guard) を定義することで、
あるスコープでの型を保証すれば大丈夫です:
function notNull<T>(item: T | null): item is T {
return item !== null;
}
const nonNullables: number[] = nullables.filter(notNull);
// OK!
あるいは
const nonNullables: number[] = nullables.filter(
(item: number | null): item is number => item !== null
);
// OK!
null
も通す
ただし、ヒューマンエラーで null
を通してしまっても
それを静的に検出はされないことに気づきました:
function notNull<T>(item: T | null): item is T {
return item === null;
}
const nonNullables: number[] = nullables.filter(notNull);
// OK! (であってほしくない)
Advanced Types - User-Defined Type Guards では
A type guard is some expression that performs a runtime check that guarantees the type in some scope.
と書かれていますが、特に実行時にもチェックされてないように思います。
なぜだろう。
解決策があれば教えてください。