TL;DR
- 型推論が効く場所では、型アノテーションは不要である。
- 理想は、関数のシグネチャには型アノテーションがあり、関数本体のローカル変数にはない状態である。
- ただし、オブジェクトリテラルと一部の戻り値の型には、推論できる場合でも型アノテーションを付ける。
内容
シグネチャにだけ型を書く
関数やメソッドのシグネチャには型アノテーションを書き、本体のローカル変数には書かないのが理想である。ローカル変数の型は、引数の型から推論される。
function logProduct(product: Product) {
const { id, name, price } = product
console.log(id, name, price)
}シグネチャであっても、引数にデフォルト値がある場合や、関数をコールバックとして渡す場合は、型アノテーションが要らない。
function parseNumber(str: string, base = 10) { ... }// Express.js
app.get("/health", (req, res) => {
res.json({ message: "Hello, world" })
})推論できても型アノテーションを付けるケース
1 つ目はオブジェクトリテラルである。型アノテーションを付けると余剰プロパティチェックが有効になる。
2 つ目は戻り値の型である。ただし付けるべきなのは、return が複数ある場合、公開 API の一部である場合、名前付きの型を返したい場合に限られる。戻り値の型を書くと、次の利点がある。
- 最初に完全な型を書くことで、本当に必要な関数を実装できる(TDD に近い考え方)。
- TypeScript が戻り値の型を解析する手間を省ける(項目78)。
- 名前付きの型を返せる。
たとえば次の add の戻り値は、{ x: number; y: number; } と推論される。
interface Vector2D {
x: number
y: number
}
function add(a: Vector2D, b: Vector2D) {
return { x: a.x + b.x, y: a.y + b.y }
}これを Vector2D として扱いたい場合は、function add(a: Vector2D, b: Vector2D): Vector2D と戻り値の型を明示する。