定数には必ず as const をつけよう!
はじめに
こんにちは!
最近は就活から逃げてニッチな技術系イベントに参加し、企業の方に「学生なのにこんなイベントに来ていて偉いね」と褒められることが生きがいの 27 卒学生エンジニアの yossuli です。
本記事は #Progate_Bar での発表内容を記事にしたものです。
今回は僕が個人開発で定数に as const
をつけるととても開発体験が向上したので、その理由と具体例を紹介します。
as const とは?
変数宣言のときに、末尾に as const をつけるとその値を readonly にした上で、リテラル型にしてくれます。
プリミティブ型の値だとそこまでうま味を感じにくいですが、配列やオブジェクトリテラルに対して使うと便利です。
サバイバル TypeScript
つまり、as const
をつけることで、オブジェクトや配列の値を変更できなくし、かつその型をリテラル型に変換することで型の制限を強化することができます。
そして as const
はオブジェクトを再帰的に readonly literal
型に変換します。
as const
をつけるべきか?
なぜ定数には 先ほど述べた 2 点のメリットのうち、再帰的にリテラル型に変換されることが特に重要です。
再帰的にリテラル型に変換されることで、オブジェクトや配列の各要素の型が厳密になります。
するとインポート先で定数にホバーした際に何を代入しているかを素早く把握できるようになります。
何に役に立つの?
このことは僕がテストコードを書く際に非常に役に立ちました。
テストを書く際に、例えば重複している場合にエラーが発生し、重複がなければ正常に動作することをテストしたいとします。
その際は DEFAULT_USER
のような定数オブジェクトを用意し、そのオブジェクトのプロパティを一部変更することによって行います。
以下のような感じです
export const DEFAULT_USER = {
id: "default_user",
name: "hoge",
age: 20,
hobbies: ["reading", "gaming"],
};
const okUsers = [
DEFAULT_USER,
{
...DEFAULT_USER,
id: "second_user"
}
]
as const
をつけていない場合
const okUsers = [
DEFAULT_USER,
// ^?: { id: string, name: string, age: number, hobbies: string[] }
{
...DEFAULT_USER,
id: "second_user",
// ^idを何にすれば重複しないのかわからない!!!
},
];
このように、as const
をつけていない場合、オブジェクトのプロパティの型が厳密にならないため、具体的に各プロパティに何の値が入っているのかを確認するためには元のファイルを参照する必要が生じてしまいます。
as const
をつけた場合
const okUsers = [
DEFAULT_USER,
// ^?: { readonly id: "default_user", readonly name: "hoge", readonly age: 20, readonly hobbies: readonly ["reading", "gaming"] }
{
...DEFAULT_USER,
id: "second_user",
// ^idを"default_user"以外の値にすれば重複しない!
},
{
...DEFAULT_USER,
id: "second_user",
},
];
このように、as const
をつけることで、オブジェクトのプロパティの型が厳密になり、各プロパティに何の値が入っているのかを型で把握できるようになります。
これにより、定数にどのような値が入っているのかを確認する際に元ファイルを参照する必要がなくなり、開発効率が向上します。
まとめ
定数には必ず as const
をつけることで、オブジェクトの誤った操作を防ぐだけでなく開発体験も向上します。
皆さんもぜひ型をがちがちに固めて開発体験を向上させましょう!
最近は型パズルにはまっており、それ関連で記事をいくつか執筆していますのでご興味のある方はぜひご覧いただければなと思います。
ちなみに、本記事以外にも 4 本、今回の LT に関連して記事を挙げていますのでそちらも併せてご覧いただけると幸いです。
xのフォローもよろしくお願いします!
Discussion