3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

TypeScript 3.7 の Assertion Functions でコンパイルエラー

Last updated at Posted at 2020-01-08

エラーメッセージの意味がよくわからず、解決するまで少し時間が掛かってしまったので。

再現

const assertIsString = (val: any): asserts val is string => {
    if (typeof val !== "string") {
        throw new Error("Not a string!");
    }
}

const someValue: unknown = "foo"; // const someValue: unknown

assertIsString(someValue); // const someValue: unknown

console.log(someValue); // const someValue: string

TypeScript Playground

9 行目でエラー。

Assertions require every name in the call target to be declared with an explicit type annotation.(2775)

解決

(outdated な解決策のため折りたたみました。これはもう参考にする必要はありません。)
function assertIsString(val: any): asserts val is string {
    if (typeof val !== "string") {
        throw new Error("Not a string!");
    }
}

const someValue: unknown = "foo"; // const someValue: unknown

assertIsString(someValue); // const someValue: unknown

console.log(someValue); // const someValue: string

TypeScript Playground

どうやら asserts function は、 function で宣言すべきらしい。

解決 - 令和最新版

const assertIsString: (val: any) => asserts val is string = (val) => {
  if (typeof val !== "string") {
    throw new Error("Not a string!")
  }
}

const someValue: unknown = "foo" // const someValue: unknown

assertIsString(someValue) // const someValue: unknown

console.log(someValue) // const someValue: string

TypeScript Playground

関数内に型を書くのではなく、変数そのものに対して型宣言すればよい。
もちろん Generics も対応。

const assertNonNull: <T>(x: T | null | undefined) => asserts x is T = (x) => {
  if (x == null) {
    throw new Error("Should exist value.")
  }
}

const maybe: number | undefined = 0 as any

assertNonNull(maybe) // const maybe: number | undefined

console.log(maybe) // const maybe: number

TypeScript Playground

結論

以下の問題があるため、JavaScript では「全て Arrow function にすべき」と考えている。

  • this の参照先がわかりづらい問題
  • function を再宣言(上書き)できてしまう問題

しかし、どちらも現代的な JS/TS 開発で遭遇することは滅多になくなってしまった。
なので、「全て function で宣言すべき」としてもよいのかもしれない。

晴れて function を使う理由がなくなったので、 全て arrow function にすべき

おまけ: ESLint で function 宣言を禁止する

.eslintrc.js
/**
 * @type {import("eslint").Linter.Config}
 */
const config = {
  rules: {
    // ...
    "no-restricted-syntax": [
      "error",
      {
        selector: "FunctionDeclaration",
        message: "Do not declare function. Use arrow function instead.",
      },
    ],
    // ...
  }
}
error  Do not declare function. Use arrow function instead  no-restricted-syntax

さようなら function

参考

3
0
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
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?