TypeScriptで型を自在に扱うために必要な型アサーションについてまとめます。
型に関する記事は他にもまとめています。



型アサーション
(型アサーションを使うことによりデメリットは記事末尾に載せている参考記事に載っているので割愛)
詳しく見ていきます。
型アサーションが必要なケース
早速ですがTypeScriptで以下のコードを書いた場合、コンパイルエラーになると思いますか?
const obj1 = {}
obj1.name = '太郎'
答えは「コンパイルエラーになる」です。
エラーメッセージは以下のとおりです。
Property 'name' does not exist on type '{}'.
JavaScriptで当たり前のようにできるオブジェクトへのプロパティの追加ができません。
なぜコンパイルエラーが起こるかというとconst obj1 = {}
とすることでobj1
は「空のオブジェクト型」としてTypeScriptが型推論してしまうからです。

このような場合を防ぐために型アサーションを用います。
型アサーションを使う
では先ほどのコードに型アサーションという機能を使ってコンパイルエラーが出ないようにします。
type User = {
name: string
age: 20
}
// as 型 で型を上書きできる
const obj1 = {} as User
obj1.name = '太郎' // エラーなし
as User
とすることで{}
という空のオブジェクトにUser
という型を上書きすることができます。
型推論された型を任意の型で上書きできています。
実際にエディター(これはTypeScriptのPlay Groundですが)でもobj1
にカーソルを合わせるとUser
型として定義されているのが分かります。

型アサーションはas
を使う、と書きましたが、<型>
でも型アサーションすることができます。(ここでの<>
はジェネリクスとは別のよう)
const num: number = 100
const strNum = <string> num // strNumは文字列の'100'になる
ただし、ReactやNext.js等のフロントエンドライブラリ・フレームワークで使われるJSX構文でタグ(コンポーネント)とごっちゃになってしまい見にくいので、asを使うのが推奨されています。
型アサーションを使うケース
そもそも型アサーションは極力使わない方が良いのは前提ですが、どのような時に型アサーションを使うのかを考えると個人的にはReact Hooksの1つであるuseState
の時に使うというのがあると思います。(他にもあるだろうけど例として)
import { useState } from 'react'
type User = {
name: string
age: number
isAdult: boolean
}
const App = () => {
const [user, setUser] = useState<User>({} as User)
}
このような時に、stateの初期値を空のオブジェクトにしたい時に型アサーションを使うことでuser
というstateをUser
型の制約の範囲で更新する(プロパティの追加、変更)ことできます。
まあ、ただ初期値をちゃんと設定してあげればわざわざ型アサーションを使わずに済むのでなるべく以下の実装にしたほうが良いかと思います。
import { useState } from 'react'
type User = {
name: string
age: number
isAdult: boolean
}
const initialUser: User = {
name: '',
age: 0,
isAdult: false
}
const App = () => {
const [user, setUser] = useState<User>(initialUser)
}
上記とは別ですが、JS→TSのリプレイスでとりあえずany型を使いたくない時に暫定で型アサーションを使う、というケースもあるかと思います。(僕自身は経験ないので完全に憶測です。悪しからず…)
最後に
型アサーションは便利ではあるけど、なるべく使わない、使うとしてもデメリットもある(世の中の上手い話には落とし穴があるのを一緒←大袈裟)のでそれを考慮した上で使うことを心掛けたいなと思います。
TypeScriptに関しては基本的な機能はある程度抑えられたかなと思うのでReact・Next.js・Laravelあたりの記事に移行しようかな。
何かTypeScriptで良い題材があればまた書きます。
参考記事

コメント