as const って何?「値=型」にできるTypeScriptの型ガード術

「as const」って何?「値=型」にできるTypeScriptの型ガード術 知識
「as const」って何?「値=型」にできるTypeScriptの型ガード術
この記事は約7分で読めます。

未経験でも気軽に!サブスク型プログラミングスクール【Freeks】

困ってた自分に届けたい話

TypeScript定数を定義して、あとからそのまま型にも使いたいとき。

「書いた値を使って型をつくったはずなのに、string型になってる…」
「え、これユニオン型じゃないの?なんで?」
って何回もなった。

毎回型を別で書き直すの、地味に面倒くさいしミスも増える。
そんなときに知った as const、たった一言で「値=型」になって、ほんとに楽になった。

てんハロ運営者
てんハロ運営者

この記事は、同じように困っていた方への備忘録兼シェアとして書いています。

as constとは?

as const は TypeScript の構文で、値を“そのまま”の形で型として固定するための書き方です。

const COLORS = ["red", "blue", "green"];

このとき、COLORS の型は string[] になります。
つまり、 "yellow" など本来想定していない値も通ってしまう可能性があります。

しかし as const を使うと

const COLORS = ["red", "blue", "green"] as const;

これだけで、型はこうなります。

readonly ["red", "blue", "green"]

中身の "red" | "blue" | "green" を型として使えるようになります。この状態になると、「この配列の中には、決まった値しか入っていない」と型で表現できるようになります。

「型」ってそもそも何?

TypeScriptでは、以下のような基本的な型(プリミティブ型)があります。

型名意味
string文字列"hello"
number数値42
boolean真偽値true / false
string[]文字列の配列["a", "b"]

多くの人は「型=stringやnumberのこと」と思っているはずです。
でも、TypeScriptには他にも重要な型の考え方があります。

リテラル型とユニオン型の違い

リテラル型:特定の値だけを許す型

const color: "red" = "red"; // "red" だけOK

ユニオン型:複数の値の中からどれか1つを許す型

type Color = "red" | "blue" | "green";

つまり、リテラル型は1つだけOK、ユニオン型は”いくつかから1つ選ぶ”感じです。

配列で使う as const

たとえば、次のようなコードがあります。

const COLORS = ["red", "blue", "green"] as const;
type Color = typeof COLORS[number];
// → "red" | "blue" | "green"

📓 説明

  • as const:配列の中身を変更できないようにし、”red” などの固定値として扱う
  • typeof COLORS[number]:配列内の要素を全部取り出して、型にする

これで Color型には “red”、”blue”、”green” だけが使えるようになります。

🔍 なぜnumberを使うの?

type Color = typeof COLORS[number];

この number は「配列の中のすべての値を取り出す」という意味です。配列は COLORS[0], COLORS[1] のように数字(=number)でアクセスします。

だから COLORS[number] と書くと、「すべてのインデックス番号に対応する値=全要素」を指すことになります。これは TypeScript の決まり文句なので、覚えてしまえばOKです。

オブジェクトで使う as const

const STATUS = {
  OK: 200,
  NOT_FOUND: 404,
} as const;

type StatusCode = typeof STATUS[keyof typeof STATUS];
// → 200 | 404

📓 説明

  • as const:オブジェクトの中身(200 や 404)を固定する
  • typeof STATUS[keyof typeof STATUS]:すべての値をまとめて型にする

結局何が便利なの?

as const を使うと、値と型の“二重管理”が不要になります。
たとえば、ボタンの種類を定義しておきたいとき:

const BUTTON_TYPES = ["primary", "secondary", "danger"] as const;
type ButtonType = typeof BUTTON_TYPES[number];

このようにしておけば:

  • 値としてボタンタイプを配列で定義
  • 型としてもそのまま使える(”primary” | “secondary” | “danger”)

あとから値を追加・削除しても、型も一緒に変わるので、管理がラクになってミスも防げるんです。

as const のメリット

❌ as const なし

const roles = ["admin", "user"];
type Role = typeof roles[number]; // → string

"admin" でも 定義していない "manager" でも通ってしまいます。

✅ as const あり

const roles = ["admin", "user"] as const;
type Role = typeof roles[number]; // → "admin" | "user"

型が限定され、間違った値を弾けるようになります。

てんハロ運営者
てんハロ運営者

おつかれさまでした!

更新をF5連打で待つの、そろそろやめませんか?
( ブログ更新をメールでそっとお知らせします🙇‍♂️ )

スパムはしません!詳細については、プライバシーポリシーをご覧ください。

コメント