18
6

More than 3 years have passed since last update.

この直し方→Assertions require every name in the call target to be declared with an explicit type annotation.

Posted at

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ができないのだと思います。本当のところどうなのかはわからないので、知っている人は教えて下さい。

18
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
6