エラーメッセージの意味がよくわからず、解決するまで少し時間が掛かってしまったので。
再現
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
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
どうやら 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
関数内に型を書くのではなく、変数そのものに対して型宣言すればよい。
もちろん 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
結論
以下の問題があるため、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
参考