🔖

RFH(react-hook-form)のヘルパーを理解したい(compact)

に公開2

コードリーディング

compact.ts
export default <TValue>(value: TValue[]) =>
  Array.isArray(value) ? value.filter(Boolean) : [];

引数に配列を取り、配列の中のfalsyを取り除いています。

疑問

valueは引数の型で配列であることが確定しているのに、なぜArray.isArray(value)をしているのか。

Chatに聞いてみた

Q.この関数でArray.isArrayをする理由が知りたいです。
引数の型は配列しか入らないのにこれをする理由はありますか。

A.Array.isArray(value)のチェックは、関数が配列以外の値で呼び出された場合のエラーを防ぐためのものです。もし配列以外の値が渡された場合、この関数は空の配列を返します。これにより、関数は常に配列を返すことが保証され、呼び出し元は結果を安全に配列として扱うことができます。

このような防御的プログラミングのテクニックは、特にライブラリや公開APIを作成する際に有用です。これにより、関数が予期しない入力で呼び出された場合でも、適切に動作することが保証されます。

Q.ですが、これはTypeScriptのコードです。

A.すみません、その点を見落としていました。あなたが指摘した通り、TypeScriptでは静的型チェックが行われ、この関数にはTValue[]型の引数が渡されることが期待されます。そのため、理論的にはArray.isArray(value)のチェックは不要です。

しかし、実際の運用環境では、TypeScriptの型チェックが常に保証されるわけではありません。TypeScriptは最終的にJavaScriptにトランスパイルされ、実行時には型情報が失われます。そのため、実行時には予期しない型の引数が関数に渡される可能性があります。

また、TypeScriptのコードがJavaScriptのコードと共存するプロジェクトでは、JavaScriptから呼び出される可能性もあります。その場合、JavaScriptからの呼び出しでは型チェックが行われないため、Array.isArray(value)のチェックが有用になる可能性があります。

したがって、Array.isArray(value)のチェックは、TypeScriptの静的型チェックだけに依存せず、実行時のエラーを防ぐための追加の保護措置と考えることができます。

...なるほど。
トランスパイルが起こった後に予期せぬ形で配列以外の型が入った時のために書いているんですね。
でもそんなことってあるんでしょうか?

詳しい方がいたらご教授いただきたいです。

Discussion

Honey32Honey32

失礼します。

value.filter(Boolean)

value.filter(v => Boolean(v))

と同じ意味で、「value という配列から、truthy な値だけを通して、falsy な値は取り除く」という意味です。 (Boolean(v) は、v が truthy のときに true, falsy のときに false になります。array.filter(fn) は array のうち fn(1つの要素) が true になるような要素だけからなる新しい配列を出力します)

参考:

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Boolean#論理値への型強制


 Array.isArray(value) 

とわざわざチェックする理由を勝手に推察すると、「フォームの状態管理をする」という性質上、実際にどんな値が入っているか分からないから、だと思います。

Corsola25Corsola25

うわ、、、
恥ずかしいミスしてました🤦‍♂️

ご教授頂きありがとうございます。