TypeScriptで「Assertions require every name in the call target to be declared with an explicit type annotation.」というコンパイルエラーが出たときの直し方です。
どのようなときに発生するコンパイルエラーか?
このエラーは、Assertion Functionsを次のようなアロー関数で定義したときに発生します。
const assertString = (value: unknown): asserts value is string => {
if (typeof value !== 'string') {
throw new Error('Value must be string')
}
}
let value: unknown
assertString(value) // コンパイルエラー
const str: string = value
このエラーの直し方
このエラーの直し方は2つあります。
直し方1: function
で書き直す
ひとつめは、アロー関数をやめてfunction
で書き直す方法です。
function assertString(value: unknown): asserts value is string {
if (typeof value !== 'string') {
throw new Error('Value must be string')
}
}
let value: unknown
assertString(value) // OK!
const str: string = value
直し方2: 変数の型を明示する
ふたつめの直し方はアロー関数の変数の型を明示する方法です。
type AssertString = (value: unknown) => asserts value is string
// ↓変数の型を明示
const assertString: AssertString = value => {
if (typeof value !== 'string') {
throw new Error('Value must be string')
}
}
let value: unknown
assertString(value) // OK!
const str: string = value // Also assignable!
上の例では型エイリアスを定義した上で、変数の型を明示していますが、型エイリアスを使わない書き方でもOKです:
// 変数の型アノテーションに直接関数のシグネチャを書く
// |-----------------------------------------|
const assertString: (value: unknown) => asserts value is string = value => {
if (typeof value !== 'string') {
throw new Error('Value must be string')
}
}
型エイリアスを使うか使わないかはお好みで。
なぜこのエラーが発生するか?
どうしてこのようなエラーが発生するのかは分かりませんが、下記のissueによれば、この仕様は意図的なものだそうです。
これは想像ですが、コンパイラの都合上、control flow analysis→変数の型推論の順番で行われていて、通常のアロー関数の書き方だと、その型推論がまだ行われていないため、control flow analysisができないのだと思います。本当のところどうなのかはわからないので、知っている人は教えて下さい。