TypeScriptを使用しているとき、型の推論が意図通りではない部分があります。
そのような場合に役立つアプリケーションコードとして、ts-resetが挙げられます。
ts-resetとは
ライブラリではなく、アプリケーションコードで使用するように設計されているようです。
インポートするだけで、TypeScriptの組み込み型付けを補正してくれます。
どういった推論になるのか、代表的なメソッドに絞って検証していきます。
.filter(Boolean)
配列の各要素に対して実行するテスト関数で、falseを返した要素を取り除きます。
実装前
推論結果にundefinedが含まれています。
以下のコードでundefinedは入らないことが決まっていますので、falsyな値を除いた型を返して欲しいです。
const filteredArray = [1, 'a', null, undefined].filter(Boolean)
// (string | number | null | undefined)[]
実装後
falsyな値はなくなり、残りの型の推論だけ行われていることが確認できます。
import '@total-typescript/ts-reset/dist/filter-boolean'
const filteredArray = [1, 'a', null, undefined].filter(Boolean)
// (string | number)[]
JSON.parse
文字列をJSONとして解析し、文字列によって記述されているJavaScriptの値やオブジェクトを構築するメソッドです。
実装前
推論結果はany型になっており、なんでも受け付けてしまいます。
const json = JSON.stringify({
name: 'John'
})
const parse = JSON.parse(json) // any
実装後
unknown型に推論されます。
これで型がより強固になり、型ガードを使用して型推論するようになっています。
import '@total-typescript/ts-reset/dist/json-parse'
...
type Props = {
name: string
}
// エラー
const parse = JSON.parse(json) // unknown
console.log(parse.name) // 'parse' is of type 'unknown'
// 型ガード
function isParseProps(value: unknown): value is Props {
return typeof value === 'object' && value !== null && 'name' in value
}
if (isParseProps(parse)) {
console.log(parse.name) // parse: Props
}
json()
fetch APIを使用している場合、json()メソッドを使用してデータを取得していきます。
実装前
json()使用後は型はany型になっています。
fetch('/')
.then(res => res.json())
.then(json => {
console.log(json) // any
})
実装後
unknownとなります。
JSON.parse()と同じく、型ガードを使用して型推論するようになっています。
import "@total-typescript/ts-reset/dist/fetch";
fetch('/')
.then(res => res.json())
.then(json => {
console.log(json) // unknown
})
includes on as const
includesメソッドは配列内に指定した値があるかを検査してくれます。
ここでは、定数にas constを使用した場合の挙動を見ていきます。
実装前
as constを使用したことで、テストする文字列の引数はusersの中の値に絞られています。
以下のように、入力した値がusersにあるか確認したい時には不都合です。
const users = ['a', 'b', 'c'] as const
const isUser = (input: string) => {
// Argument of type 'string' is not assignable to parameter of type '"a" | "b" | "c"'
if (users.includes(input)) {
console.log(input)
}
}
実装後
as constでリテラル型として扱われていた型がstring型まで拡張されています。
これにより、不都合な型の絞り込みを解消できます。
import '@total-typescript/ts-reset/dist/array-includes'
...
// string
if (users.includes(input)) {
console.log(input);
}
...
個人的な使用感
組み込みTypeScriptでは届かない部分を補ってくれた印象です。個人的にはfilterメソッドの改善が嬉しいです。
使用頻度の高いメソッドに対して導入していき、型をより強固にする方法がいいかと感じます。
他にも対応しているメソッドがありますので、詳細はドキュメントから確認してください。
最後に
GoQSystemでは一緒に働いてくれる仲間を募集中です!
ご興味がある方は以下リンクよりご確認ください。