はじめに
TypeScriptのconstアサーションについて学びます。
as constを使用すると、オブジェクトや配列に対してreadonlyが適用され、値もリテラル型として推論されます。
この記事では、具体的なコードを通して、as constの2つの効果を見ていきます。
readonlyになる
通常のオブジェクト
まずは、書籍情報を表すオブジェクトを定義します。
const book = {
title: "TypeScript Basic",
authors: [
{
name: "Liam",
role: "author",
},
{
name: "宇野 武",
role: "translator",
},
],
publisher: {
name: "エンジニア出版",
},
categories: ["プログラミング", "TypeScript"],
price: 5000,
};
このオブジェクトに対して、プロパティの変更や配列の操作を行えます。
book.title = "JavaScript Basic";
book.authors = [];
book.publisher.name = "技術評論社";
book.categories.push("Java");
book.categories[0] = "JavaScript";
book.price = 3000;
constアサーションを利用する
次に、オブジェクトの末尾にas constを付けてみます。
const book = {
title: "TypeScript Basic",
authors: [
{
name: "Liam",
role: "author",
},
{
name: "宇野 武",
role: "translator",
},
],
publisher: {
name: "エンジニア出版",
},
categories: ["プログラミング", "TypeScript"],
price: 5000,
} as const;
この状態で、先ほどと同じようにプロパティや配列の要素を変更しようとすると、TypeScriptの型チェックでエラーになります。
再帰的にreadonlyが適用されるため、オブジェクトのプロパティや配列の要素を変更できなくなります。
配列への要素の追加や削除もできません。
// Cannot assign to 'title' because it is a read-only property.
book.title = "JavaScript Basic";
// Cannot assign to 'authors' because it is a read-only property.
book.authors = [];
// Cannot assign to 'name' because it is a read-only property.
book.publisher.name = "技術評論社";
// Property 'push' does not exist on type 'readonly ["プログラミング", "TypeScript"]'.
book.categories.push("Java");
// Cannot assign to '0' because it is a read-only property.
book.categories[0] = "JavaScript";
// Cannot assign to 'price' because it is a read-only property.
book.price = 3000;
リテラル型として推論される
as constを付けると、値がリテラル型として推論されます。
例えば、先ほどのbookオブジェクトの場合、各プロパティの型は次のようになります。
| プロパティ |
as constなし |
as constあり |
|---|---|---|
title |
string |
"TypeScript Basic" |
price |
number |
5000 |
publisher.name |
string |
"エンジニア出版" |
通常は文字列がstring型、数値がnumber型として推論されますが、as constを付けると、具体的な値そのものが型になります。
この性質を利用すると、オブジェクトに定義した値から型を生成できます。
例えば、注文ステータスを表すオブジェクトを定義します。
const STATUS = {
PENDING: "pending",
COMPLETED: "completed",
CANCELLED: "cancelled",
} as const;
as constを付けることで、それぞれのプロパティがリテラル型として推論されます。
このオブジェクトから、次のように型を生成できます。
type Status = typeof STATUS[keyof typeof STATUS];
// "pending" | "completed" | "cancelled"
生成した型は、関数の引数などに利用できます。
function updateStatus(status: Status) {
// ステータスを更新する処理
}
updateStatus(STATUS.PENDING); // OK
updateStatus(STATUS.COMPLETED); // OK
updateStatus("unknown"); // エラー
まとめ
今回は、TypeScriptのas constについて紹介しました。
as constには、主に2つの効果があります。
-
readonlyを適用し、オブジェクトや配列の変更を型レベルで制限する - 値をリテラル型として推論し、具体的な型情報を保持する
as constは、オブジェクトや配列を読み取り専用として扱いたい場合や、定義した値から型を生成したい場合に便利な構文です。
参考
- 菅原浩之(2024)『現場で使える TypeScript 詳解実践ガイド』マイナビ出版、p.124