TypeScriptでインスタンスを生成するときに、プロパティの初期値をどうするべきなのか……。最近ずっと気になっていた事柄だったので、考えをまとめてQiitaに投稿しました。
投稿の中で、自分がよく使う初期値の方針をまとめました。
null
null
か0
null
null
null
自分の傾向をまとめると、「型の種類を増やしたくないからできるだけnullは使いたくないけど、どうしようもないときはnullを初期値にする。undefinedは本当の未定義と見分けがつかないので初期値としては避ける」ということになります。
null
とundefined
にまつわる指摘と議論この投稿の公開後に早速コメントがあり、nullはよく考えてから使ったほうが良いという指摘と参考記事を紹介されました。
提示されたGitHub Issueで話題になっていた問い掛けは「JavaScriptのユーザーランドではnullを廃止してundefinedに統一するべき」というものでした。
スレッドの中で明確な結論は出ていませんでしたが、nullの利用について肯定・否定の両派から意見が寄せられていました。
null
を肯定する意見
null
を利用しているnull
とundefined
は意味が違うので、使い分ければよい。null
にはundefined
より明示的に値が存在しないという意味があるので、その意味で使うべきnull
は表現できるが、undefiend
は表現できないnull
に否定的な意見
null
を使う仕様は変えられないが、ユーザーランドは別null
とundefined
が両方存在している現状が間違っているし、誰もちゃんと使い分けを知らない(だからundefined
に寄せるべき)undefined
を扱う代替手段はどうとでもできるnull
を使う場合には意図を明確にするべき他言語の経験がなくWebデザインの延長で開発をやるようになった自分にとって、この議論は興味深かったです。
僕にとってJavaScriptにnull
とundefined
が存在するという仕様は当然なことで、そこに疑問を持ったことはありませんでした。
その仕様には何か特別な理由があり、自分が知らないだけで上級者はちゃんと使い分けているものだと思っていたのですが……。
似たような概念が2種類もあることでJavaScriptとTypeScriptの世界に無駄な混乱を招いているということは事実なようです。
確かに、使い分ける理由がないのであれば、寄せられる方に統一するべきでしょう。寄せるのであれば、null
よりもundefined
の方がより一般的なので適当です。
一方で、既存のAPIの仕様がある以上絶対にnull
を無くすこともできません。
結局寄せ切ることはできませんが「null
の利用は明確な意図がない限りは最小限にするべき」という程度のことは言えるかもしれません。
undefined
だけを使うnull
を使うのであれば利用意図を明確にするnull
は甘受するさて、冒頭のプロパティ初期値の話題に戻ったとき、
型の種類を増やしたくないからできるだけnullは使いたくないけど、どうしようもないときはnullを初期値にする。undefinedは本当の未定義と見分けがつかないので初期値としては避ける。
という理由付けが妥当なのかをもう一度考えてみます。
仮に初期値としてundefined
を代入したときに、本当に存在しないプロパティなのかどうかはhasOwnProperty
で調べることができます。
しかしTypeScriptでundefined
を許容する型定義をすると、コンストラクタ内でプロパティへの代入をせずにクラスを実装できてしまいます。
クラスでの実装時には、どちらの型定義でもプロパティへの代入を省略できてしまう
オプショナル型とundefinedとのユニオン型は、オブジェクトとクラスで挙動が違った - Qiita
つまり、undefined
を許容する型定義ではプロパティの存在を保証できません。
それを保証したければ、コンストラクタ内でプロパティにundefined
を代入する運用が必要です。コンパイラが見てくれないのでちょっと面倒そうです。
class MyClass {
public hoge: string | undefined;
constructor() {
// 書かなくてもコンパイルは通るが、省略するとhasOwnPropertyで区別できなくなる
this.hoge = undefined;
}
}
しかし、当初のnull
を使う理由であった「本当にプロパティ未定義な状態と、値がない状態を区別できる」という機能が実際に必要な状況がどれだけあるでしょうか?
経験上、それが本当に必要だったシーンはこれまでありませんでした。また、その機能が必要な状況を思いつくことも自分には難しいです。
オブジェクトのプロパティを走査するような機能には関係しそうですが、たとえばディープコピーするときにundefinedなプロパティが律儀に複製されても、そんなに嬉しい状況がなさそうです。
理由が思いつかないのであれば、やはりnull
にこだわる意義はないかもしれません……。
null
を使いたいですか?最後に、例のIssueを立てた人がTwitterで行っているnull
とundefined
にまつわるアンケートを転載しました。あなたはどちら派でしょうか?
If you don't want to comment in that thread. Vote instead. But read the arguments for dropping `null` first.
— Sindre Sorhus (@sindresorhus) April 7, 2019
TypeScript公式リポジトリのWikiにnull
を使ってはいけないという記述を見つけましたが、これはコンパイラの開発者向けガイドであり、TypeScriptそれ自体のためのガイドではありません。
STOP READING IMMEDIATELY THIS PAGE PROBABLY DOES NOT PERTAIN TO YOU These are Coding Guidelines for Contributors to TypeScript This is NOT a prescriptive guideline for the TypeScript community
Coding guidelines · microsoft/TypeScript Wiki
※投稿内容は私個人の意見であり、所属企業・部門見解を代表するものではありません。