😌

[TypeScript] 型にハテナ(?)をつけるのって、undefinedを指定するのと何か違うの?[オプショナルプロパティ]

2024/03/01に公開

こんにちは😊 kesojiです。

最近弊社では丸一日かけて、Vue3/TypeScriptの内製研修を実施しました。

Vue3/TypeScriptにおける便利さや、初学者がつまずきがちな内容について学習しました。

今日はそんなTypeScriptにおけるnullundefinedと、この?について話します。

type Hoge = {
    fuga?: string //←このハテナ
}

ちなみに、この ? をつけたものは「オプショナルプロパティ」と呼ばれます。 ? 自体は「オプショナルプロパティマーカー」って言うみたいです。たぶん。。(ググラビリティが低いですよねこれ。そういうのはChatGPTに聞くとよいです。「TypeScriptの型定義の?ってなんていうの?」。)

論より証拠

とりあえず動かしながら確認してみましょう! TypeScript Playground に実際のコードがありますので、是非こちらで実際のTypeScriptエラーも確認しながら見て頂くと理解が深まるとおもいます。

少々無理矢理な部分がありますが、以下の型のバリエーションを考えてみます。

type stringのみ = {
    data: string
}

type stringundefined = {
    data: string|undefined
}

type stringnull = {
    data: string|null
}

type stringundefinednull = {
    data: string|undefined|null
}

type ハテナつきstringのみ = {
    data?: string
}

type ハテナつきstringundefined = {
    data?: string|undefined
}

type ハテナつきstringnull = {
    data?: string|null
}

type ハテナつきstringundefinednull = {
    data?: string|undefined|null
}

これらを受け取る関数を定義します。読みにくいですが、全て同じパターンです。

function stringのみ(a: stringのみ){}
function stringundefined(a: stringundefined){}
function stringnull(a: stringnull){}
function stringundefinednull(a: stringundefinednull){}
function ハテナつきstringのみ(a: ハテナつきstringのみ){}
function ハテナつきstringundefined(a: ハテナつきstringundefined){}
function ハテナつきstringnull(a: ハテナつきstringnull){}
function ハテナつきstringundefinednull(a: ハテナつきstringundefinednull){}

そして、ここから実際に関数を呼び出して型エラーが出るか、挙動を確認していきましょう。

文字列を入れてみる

文字列を入れてみます。これはもちろん全部問題無く入りますね。

nullを入れてみる

nullを入れてみます。nullを許容していない型でエラー(赤下線)が出ました。

undefinedを入れてみる

undefinedを入れてみます。ハテナつきの様子が変わってきましたね!

プロパティごと無いものを入れてみる

最後に、そもそもプロパティが無いものをいれてみましょう。ハテナがついていないものは全てエラーになってしまいました。

ちなみに引数無しは

最後といいましたが、引数無しはどうなるでしょうか。 答えはPlaygroundにはあります!

解説?

もう既に全て説明してしまった感もありますが、

型定義の?undefinedを許容し、かつ、プロパティそのものが未定義も許容する

となります。そもそもundefinedって日本語では未定義では...?って気持ちにもなりますが、そうなった方は参考資料を見てみて下さい(投げ)。

使い分け方の指針(あくまでこれは個人的なものです)

  • 未定義やundefinedの場合がある時は、 ? を使っておけばOK。
    • |undefined と書くより簡単
    • 実用上問題ない(と思っている)
  • どうしても明確にundefinedと定義したい場合が思い付きませんでした。
    • 既存コードやライブラリの都合上...?
    • 定義がある場合と定義がない場合を区別しつつ、かつ定義された値で undefined が特別な意味を持つ場合...? (nullは使わないと決めつつ、「設定項目を空っぽにした」みたいな状態に意味があるようなアプリの場合?)

参考資料

以下がとても詳しいため、より深く学びたい人、理論から学びたい人、そもそもundefinedとnullはどう使い分けるべきなのか?と思った人は是非読んでみましょう!
undefinedとnullの違い - サバイバルTypeScript
nullとundefined - TypeScript Deep Dive 日本語版

最後に

弊社ではだいたい月1回を目標に、エンジニア全体でトレーニングを実施しています。AWS JAMのようなグループワークと、座学多めの講義を隔月で行っています。
一緒に働く/一緒に成長するメンバーを募集中です!雰囲気だけでも是非知っていただきたく、↓のカジュアル面談を気楽にお申し込み下さい!

ソーシャルデータバンク テックブログ

Discussion