as const は「この値をそのままの形で固定して」と伝えるスイッチ
as const は、TypeScript に対してこう宣言するためのものです。
「この値は“変わらない前提”だから、できるだけそのままの形・そのままの値で扱ってほしい」
具体的には、as const を付けると次のことが起こります。
- 値が「広い型」ではなく「リテラル型」にまでギュッと絞られる
- 配列やオブジェクトの場合、その中身が
readonly(書き換え禁止)になる
つまり、「値」と「型」と「変更不可」の3つを一気に固める宣言が as const です。
const arr = [1, 2, 3];
// 型: number[]
const arrFixed = [1, 2, 3] as const;
// 型: readonly [1, 2, 3]
TypeScript同じ配列でも、as const を付けた瞬間に「意味のある定義」に変わります。
普通の const と as const の違いを具体例で見る
const だけの場合(まだ“ゆるい”状態)
まずは const だけのとき。
const colors = ["red", "green", "blue"];
// 型: string[]
TypeScriptここで TypeScript が知っているのは「文字列の配列」ということだけです。
中身が "red" なのか "yellow" なのかまでは、型としては区別していません。
colors.push("yellow"); // 型的にはOK
TypeScriptconst は「変数そのものの再代入」を禁止するだけで、
配列の中身やオブジェクトのプロパティは、まだ変更可能です。
as const を付けた場合(“ガチガチに固定”された状態)
同じものに as const を付けると、こう変わります。
const colors = ["red", "green", "blue"] as const;
// 型: readonly ["red", "green", "blue"]
TypeScriptここで起きていることは、
- 配列の要素が
"red" | "green" | "blue"という文字列リテラル型に固定される - 配列自体が
readonlyになり、pushや書き換えができなくなる
という、「定義した通りの値・順番・個数を、そのまま型として扱う」状態です。
// colors.push("yellow"); // エラー
// colors[0] = "black"; // エラー
TypeScript「この配列は“定義そのもの”が意味を持つ。あとから変えられたら困る」
というときに、as const はぴったりハマります。
オブジェクトに対する as const の効果
プロパティが「リテラル型+readonly」になる
オブジェクトでも同じです。
const config = {
env: "production",
timeout: 5000
} as const;
TypeScriptこのときの型は、イメージとしてはこうなります。
{
readonly env: "production";
readonly timeout: 5000;
}
TypeScriptつまり、
envは"production"以外にならないtimeoutは5000以外にならない- どちらも再代入できない
という、かなり“固い”オブジェクトになります。
// config.env = "dev"; // エラー
// config.timeout = 1000; // エラー
TypeScript設定値や定数テーブルのように、「ここに書いた値そのものが仕様だ」というデータには、as const がとても相性がいいです。
as const の一番おいしい使い方:配列から「選べる型」を作る
as const が実務で一番輝くのは、「選択肢の配列」から「選べる値の型」を作るときです。
const COLORS = ["red", "green", "blue"] as const;
// 型: readonly ["red", "green", "blue"]
type Color = (typeof COLORS)[number];
// Color は "red" | "green" | "blue"
TypeScripttypeof COLORS は readonly ["red", "green", "blue"] というタプル型になり、[number] を付けることで「その配列の要素の型」、つまり "red" | "green" | "blue" を取り出せます。
これで、
let c: Color;
c = "red"; // OK
c = "blue"; // OK
// c = "yellow"; // エラー
TypeScriptという、「この3色だけ」という型を簡単に作れます。
UI の選択肢、API の固定値、状態の種類などで、めちゃくちゃよく使うパターンです。
readonly と as const の違いも軽く整理しておく
readonly と as const は似た匂いがするので、ここで一度整理しておきます。
readonlyは「型の中で“変更禁止”を指定する」as constは「値の末尾に書いて、“リテラル型+readonly”に一気に変換する」
たとえば:
type User = {
readonly id: number;
name: string;
};
const user: User = { id: 1, name: "Taro" };
// user.id = 2; // エラー(readonly)
// user.name = "Jiro"; // OK
TypeScriptこれは「型側に readonly を書いている」パターン。
一方で:
const user = {
id: 1,
name: "Taro"
} as const;
TypeScriptこれは「値側に as const を書いて、id: 1(リテラル型)かつ readonly、name: "Taro"(リテラル型)かつ readonly
にしている」パターンです。
初心者向け as const の実践的な感覚
難しいことを全部抜きにして、まずはこう覚えておくといいです。
- 「この配列・オブジェクトは“定義そのもの”が意味を持つ。変えたくない」
→as constを付ける - 「この配列から“選べる値の型”を作りたい」
→const OPTIONS = [...] as const+type Option = (typeof OPTIONS)[number]; - 「定数の値と型をズラしたくない」
→const X = "foo" as const; type XType = typeof X;
as const は、
「この値、本当に固定なんだよ」というあなたの設計意図を、
TypeScript に全力で理解させるためのスイッチです。
VSCode で、as const を付けたり外したりして、
ホバーしたときの型表示がどう変わるかを眺めてみてほしい。
それを何回か繰り返すだけで、「ああ、これは“値をそのまま型にするボタン”なんだな」という感覚が、ちゃんと自分のものになっていきます。
