なにを言ってるんだァおめー?と思っている人が居たらそれは正しくて、あたしもこのタイトルを書いておいて(コンテキスト0だとあたりまえ体操だな)となっているワケですわね。
例題
2つの等しい value を持つ object が存在するとして、共通の value のみ残した object を作りたいと思う
const values = { hoge: 'fuga', moge: 'piyo', } as const; const searchTarget = { hoge: 'fuga', moge: 'boeeeee', }; // values と searchTarget で共通の value を持つキーのみ残したものを作りたい // const newValue = { hoge: 'fuga' }; // のような
このとき Object#fromEntries と Object#entries を使って以下のような実装をすると思う
Object.fromEntries( Object.entries(searchTarget).filter( ([_, text]) => Object.values(values).includes(text) ) )
js のコンテキストとしては問題ない、がTS のコンテキストだとエラーになる
なにが問題?
エラー出力の内容の通りなのだが Object.values
で引っ張ってきた配列の型が 'fuga' | 'piyo'
になっていて Object.entries(searchTarget)
で引っ張ってくる text
が string
のため適合しないと言われる
解法
1. toString()
を経由した string
へのダウンキャスト
社で教えてもらった方法。 String#toString
を 利用( 悪用 ) しつつ Array#some
で検索するようにする
Object.fromEntries( Object.entries(searchTarget).filter( ([_, text]) => Object.values(values) .some((value) => value.toString() === text) // value の定義は 'fuga' | 'piyo' ) )
Array の存在確認系の実装は脳死で includes()
使いがちだったのだが some()
を使えば中でごにょごにょできる。
その上で value に対して toString
を使う。すると型定義が string
にダウンキャストされる
これによって型が適合する
2. Object.values
に対してジェネリクスで string
を渡す
身内の Discord のメンバーの人に教えてもらった方法。こちらはタイトルと関係ないがスマートなのでご紹介。
Object.fromEntries( Object.entries(searchTarget).filter( ([_, text]) => Object.values<string>(values).includes(text) ) )
Object.values
が実はジェネリクスを受け取れるのでこれに string
を渡してやる。
すると Object.values
の返却型が string[]
となるので includes()
を使用しても問題なくなる。
playground
Playground のリンクを載せておくので興味がある人は触ってみると良いかも。