メインコンテンツまでスキップ

constアサーション「as const」 (const assertion)

オブジェクトリテラルの末尾にas constを記述すればプロパティがreadonlyでリテラルタイプで指定した物と同等の扱いになります。

ts
const pikachu = {
name: "pikachu",
no: 25,
genre: "mouse pokémon",
height: 0.4,
weight: 6.0,
} as const;
ts
const pikachu = {
name: "pikachu",
no: 25,
genre: "mouse pokémon",
height: 0.4,
weight: 6.0,
} as const;

代入はもちろんできません。

ts
pikachu.name = "raichu";
Cannot assign to 'name' because it is a read-only property.2540Cannot assign to 'name' because it is a read-only property.
ts
pikachu.name = "raichu";
Cannot assign to 'name' because it is a read-only property.2540Cannot assign to 'name' because it is a read-only property.

readonlyconst assertionの違い

どちらもオブジェクトのプロパティをreadonlyにする機能は同じですが、以下が異なります。

readonlyはプロパティごとにつけられる

const assertionはオブジェクト全体に対する宣言なので、すべてのプロパティが対象になりますが、readonlyは必要なプロパティのみにつけることができます。

const assertionは再帰的にreadonlyにできる

オブジェクトの中にオブジェクトがあるときの挙動が異なります。たとえば次のようなオブジェクトがあるとします。

ts
type Country = {
name: string;
capitalCity: string;
};
 
type Continent = {
readonly name: string;
readonly canada: Country;
readonly us: Country;
readonly mexico: Country;
};
 
const america: Continent = {
name: "North American Continent",
canada: {
name: "Republic of Canada",
capitalCity: "Ottawa",
},
us: {
name: "United States of America",
capitalCity: "Washington, D.C.",
},
mexico: {
name: "United Mexican States",
capitalCity: "Mexico City",
},
};
ts
type Country = {
name: string;
capitalCity: string;
};
 
type Continent = {
readonly name: string;
readonly canada: Country;
readonly us: Country;
readonly mexico: Country;
};
 
const america: Continent = {
name: "North American Continent",
canada: {
name: "Republic of Canada",
capitalCity: "Ottawa",
},
us: {
name: "United States of America",
capitalCity: "Washington, D.C.",
},
mexico: {
name: "United Mexican States",
capitalCity: "Mexico City",
},
};

ここでContinentのタイプエイリアスがもつプロパティはすべてreadonlyです。よって次のようなことはできません。

ts
america.name = "African Continent";
Cannot assign to 'name' because it is a read-only property.2540Cannot assign to 'name' because it is a read-only property.
america.canada = {
Cannot assign to 'canada' because it is a read-only property.2540Cannot assign to 'canada' because it is a read-only property.
name: "Republic of Côte d'Ivoire",
capitalCity: "Yamoussoukro",
};
ts
america.name = "African Continent";
Cannot assign to 'name' because it is a read-only property.2540Cannot assign to 'name' because it is a read-only property.
america.canada = {
Cannot assign to 'canada' because it is a read-only property.2540Cannot assign to 'canada' because it is a read-only property.
name: "Republic of Côte d'Ivoire",
capitalCity: "Yamoussoukro",
};

しかしながら、次のようなことは問題なくできてしまいます。

ts
america.canada.name = "Republic of Côte d'Ivoire";
america.canada.capitalCity = "Yamoussoukro";
ts
america.canada.name = "Republic of Côte d'Ivoire";
america.canada.capitalCity = "Yamoussoukro";

これはreadonlyをつけたプロパティがオブジェクトである場合に、そのオブジェクトのプロパティまでreadonlyにはしないことに起因します。

const assertionはすべてのプロパティを固定する

as constを付けます。

ts
const america = {
name: "North American Continent",
canada: {
name: "Republic of Canada",
capitalCity: "Ottawa",
},
us: {
name: "United States of America",
capitalCity: "Washington, D.C.",
},
mexico: {
name: "United Mexican States",
capitalCity: "Mexico City",
},
} as const;
ts
const america = {
name: "North American Continent",
canada: {
name: "Republic of Canada",
capitalCity: "Ottawa",
},
us: {
name: "United States of America",
capitalCity: "Washington, D.C.",
},
mexico: {
name: "United Mexican States",
capitalCity: "Mexico City",
},
} as const;

readonlyと同様にトップレベルのプロパティへの代入はできません。

ts
america.name = "African Continent";
Cannot assign to 'name' because it is a read-only property.2540Cannot assign to 'name' because it is a read-only property.
america.canada = {
Cannot assign to 'canada' because it is a read-only property.2540Cannot assign to 'canada' because it is a read-only property.
name: "Republic of Côte d'Ivoire",
capitalCity: "Yamoussoukro",
};
ts
america.name = "African Continent";
Cannot assign to 'name' because it is a read-only property.2540Cannot assign to 'name' because it is a read-only property.
america.canada = {
Cannot assign to 'canada' because it is a read-only property.2540Cannot assign to 'canada' because it is a read-only property.
name: "Republic of Côte d'Ivoire",
capitalCity: "Yamoussoukro",
};

これだけではなくオブジェクトが持つプロパティも同様にreadonlyにしてくれます。

ts
america.canada.name = "Republic of Côte d'Ivoire";
Cannot assign to 'name' because it is a read-only property.2540Cannot assign to 'name' because it is a read-only property.
america.canada.capitalCity = "Yamoussoukro";
Cannot assign to 'capitalCity' because it is a read-only property.2540Cannot assign to 'capitalCity' because it is a read-only property.
ts
america.canada.name = "Republic of Côte d'Ivoire";
Cannot assign to 'name' because it is a read-only property.2540Cannot assign to 'name' because it is a read-only property.
america.canada.capitalCity = "Yamoussoukro";
Cannot assign to 'capitalCity' because it is a read-only property.2540Cannot assign to 'capitalCity' because it is a read-only property.

関連情報

📄️ 型アサーション「as」

TypeScriptには、型推論を上書きする機能があります。その機能を型アサーション(type assertion)と言います。

📄️ オブジェクト型のreadonlyプロパティ

TypeScriptでは、オブジェクトのプロパティを読み取り専用にすることができます。読み取り専用にしたいプロパティにはreadonly修飾子をつけます。読み取り専用のプロパティに値を代入しようとすると、TypeScriptコンパイラーが代入不可の旨を警告するようになります。
  • 質問する ─ 読んでも分からなかったこと、TypeScriptで分からないこと、お気軽にGitHubまで🙂
  • 問題を報告する ─ 文章やサンプルコードなどの誤植はお知らせください。