TypeScriptのルールをstrictにしたときにつまずいたこと
eslintをstrictにした
このブログはTypeScriptで開発しています.型定義が弱いところがあり,eslintのルールを見直してみようと思ったのがきっかけ.一つ一つ検討していくのは骨が折れるので,一旦strict系のルールを有効にしようとなりました.
strictにするにはtsconfig.json
のcompilerOptions
のstrict
フラグをtrue
にします.
// tsconfig.json
{
"compilerOptions": {
"strict": true
}
}
この結果,めちゃくちゃeslintに怒られたので,その作業ログを残します.
strict-boolean-expressions
これは,booleanでない値を暗黙的にbooleanのように評価することを規制するルール.
例えばこんなコード.
const apple = {
color?: string
}
// Unexpected nullable string value in conditional. Please handle the nullish/empty cases explicitly.
if (apple.color) {
// なんかの処理
}
apple
オブジェクトのcolor
プロパティはstring | undefined
という状況で,truthy
のときだけなにかの処理をしたいという分岐を書いています.
これのなにが問題かというと,color
プロパティがundefined
や空文字のとき(つまりfalsy
とのき)に暗黙的な型変換が行われ,if
ブロックの中が評価されるということ.いつtrue
としたくて,いつfalse
としたいかをboolean
で明確に書きなさいというルールがstrict-boolean-expresiions
だと理解しています.
ではどう書けばいいかというと,次のような感じ.
const apple = {
color?: string
}
if (apple.color !== undefined) {
// なんかの処理
}
undefined
でないときのみ,if
ブロックの中が評価されるという分岐にしました.これでエラーは消えます.空文字の場合もif
ブロック内を評価してほしいときは,さらに条件を追加する必要があります.
多少コード量が増えますが,型安全性は増しました.
参考:Falsy値を比較せずにそのまま判定に使うことはやめよう
補足:truthy
とfalsy
ちょっとここでtruthy
とfalsy
についてまとめておきます.
falsy
な値
string
型の空文字''
number
型の0
number
型のマイナスゼロ-0
number
型のNaN
bigint
型の0n
boolean
型のfalse
object
型のdocument.all
null
undefined
参考:Falsy (偽値) - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDN
filter
とsort
文字列の配列からundefinedを取り除き,ソートしたいという処理でエラーがでました.
const array = ['hoge', undefined, 'fuga', undefined]
const newArray = array
.filter((el) => el) // ここでundefinedを消したかった
.sort((a, b) => a > b) // ここで降順に並べたかった
filter
メソッドのコールバック関数の返り値はboolean
'hoge'
や'fuga'
はtruthy
で,undefined
はfalsy
なので,これで行けると思いましたが,上のstrict-boolean-expression
で怒られました.
sort
メソッドのコールバック関数の返り値はnumber
「a
やb
がundefined
のことがあるよ」と怒られました.一つ前のプロトタイプチェーンでfilter
をしているので,undefined
はないはずなのに....また,「boolean
であるa > b
ではなく,number
を返しなさい」と怒られました.
修正方法
以下のように修正しました.
const array = ['hoge', undefined, 'fuga', undefined]
const newArray = array
.filter((el): el is string => typeof el === 'string')
.sort((a,b) => b.localeCompare(a))
is
演算子を使って,filter
メソッド適用後はstring
型のみになることを明示しました.String
オブジェクトの組み込みメソッドであるlocaleCompare
でnumber
を返すように変更しました.