副業先のフロントエンド開発で!.
を初めて見て「?.
は知っているけど!.
は知らないぞ?」となったのでこの機会に両者の特徴や違いをまとめておこうと思う。
まず、両者の演算子の読み方?名前?は以下のとおり。
- ?.:オプショナルチェーン演算子
- !.:非nullアサーション演算子
タイトルには「違い」と書いているが直接的な比較ではなく、それぞれが「どんなものなのか?」についてまとめる記事にする。
?.(オプショナルチェーン演算子)
?.
はオプショナルチェーン演算子と言う。もしくはオプショナルチェイニングと呼ばれていたりするのでどちらでも良いかと思う。(どちらでも通じる)
ちなみにこれはTypeScriptではなくJavaScriptの機能。

この演算子の機能はオブジェクトやクラスのプロパティにアクセスしようと思った時にそのプロパティがnullishな値の場合、?.時点でコードの実行を終了しundefinedを返却する。
極端な例だがサンプルコードを書いてみる。
let org;
console.log(org); // undefined
console.log(org.length); // error: Uncaught TypeError: Cannot read properties of undefined (reading 'length')
console.log(org?.length); // undefined
変数org
はundefinedと定義されているので、.length
で文字列の長さを取得しようとするとエラーになる。(文字列型のデータじゃ無いので当たり前)
ただ、?.
を使うとエラーにはならず、undefinedを返却する。
これはTypeScriptの領域になるが、オプショナルチェーン演算子が入った式を変数に格納した場合、その変数のデータ型は必ず○○ | undefined
になる。
type User = {
age: number
name?: string
}
const user: User = {
age: 30
}
const nameLength = user.name?.length // データ型は number | undefined
記事タイトルから若干脱線するけど、オプショナルチェーン演算子と似たような機能を持つnull合体演算子(??)との比較や使い分けについて解説された記事があったので貼っておく。

!.(非nullアサーション演算子)
!.
は非nullアサーション演算子と呼ぶ。
これはJavaScriptではなくTypeScriptの機能。
この演算子の機能は、nullishの可能性のあるプロパティがnullishではないこと、つまりnullでもundefinedでもないことをコンパイラーに教えてあげる(保証してあげる)こと。
名前が「非null〜」であるが、nullish(null または undefined)を指す。
先ほど使ったサンプルコードで名前をオプションのプロパティを持つユーザーオブジェクトの名前の文字列長さに100を足してコンソールに出力するコードを書く。
type User = {
age: number
name?: string
}
const user: User = {
age: 30
}
const nameLength = user.name?.length
console.log(nameLength + 100) // Object is possibly 'undefined'.
nameLength
がundefinedの可能性を持つ以上、undefined + 100
はエラーになる。
このコードではnameを持たないオブジェクトを例にしているが、nameはオプショナルなプロパティであり、操作するオブジェクトはnameを持っている条件で考える。
type User = {
age: number
name?: string
}
const user: User = {
age: 30,
name: 'サンプル太郎'
}
const nameLength = user.name.length // Object is possibly 'undefined'.
console.log(nameLength + 100)
user
オブジェクトにname: 'サンプル太郎'
を定義&オプショナルチェーン演算子を消したとしてもUser
型の段階でnameはstring | undefined
なので、user.name.length
が「Object is possibly ‘undefined’.」でコンパイルエラーになり、やはりuser.name?.length
にする必要がある→出力コードはエラーになる。
もったいぶった説明になってしまったけど、ここで!.
の登場。
type User = {
age: number
name?: string
}
const user: User = {
age: 30,
name: 'サンプル太郎'
}
const nameLength = user.name!.length // number
console.log(nameLength + 100) // 106
user.name!.length
でnameプロパティがnullsihではないことを保証することでnumber型となり、コンソールの出力は成功する。
最後に
これまでReactでのフロントエンド開発をする上では?.
しか使ったことがなかったけど、オプショナルなプロパティにアクセスした得られる値を後続の処理にも使いたい場合は!.
を使う必要があることがわかったのと両者の違いがわかった。
余談だが、JavaScript、TypeScriptでオブジェクトやクラスのプロパティにアクセスする時の.
(例:response.data
)はチェーン演算子と呼ぶ。
コメント