kqito's 技術ブログ

技術やプログラミングについて思ったことを呟くブログ

TypeScript Widening Literal Types

はじめに

こんにちは。Webフロントエンドを専攻しているkqitoです。

今回はTypeScript独自仕様のWidening Literal Typesについて簡単なサンプルを用いながらメモします

メモ

Widening / NonWidening Literal Types

TypeScriptには Widening Literal TypesNonWidening Literal Types という2つのLiteral Typesが存在しています。

まずは以下のコードを見てみましょう。

const widening = "HOGE"; // widening: "HOGE"

当たり前ですが、 widening という変数は"HOGE"のみを許容するString Literal Typesです。また、これは暗黙的に Widening Literal Types と定義されます。 しかし、これをオブジェクトのプロパティとした時に意図せぬ挙動を行う可能性があります

以下のコードを見てみましょう。

const widening = "HOGE"; // widening: "HOGE"

const test = {
  widening // widening: string <- !?!?!?
};

test.widening = "あああああああ";

console.log(test.widening); // あああああああ

オブジェクトのプロパティとすると純粋なString Literal Typesになってしまいました。 これがWidening Literal Typesの挙動です。

as const

このようなオブジェクトの中でも"HOGE"のみを許容するString Literal Typesで定義したい場合は NonWidening Literal Types で定義することで挙動を変更することができます。

以下のコードのように as const を利用することで変数を NonWidening Literal Types として定義することができます。

const nonWidening = "HOGE" as const; // nonWidening: "HOGE"

const test = {
  nonWidening // nonWidening: "HOGE"
};

test.nonWidening = "あああああああ"; // Error: Type '"あああああああ"' is not assignable to type '"HOGE"'.

ちなみに

尚、as const を使用せず記述する場合(普通はそんなことしないと思うのですが、as constがサポートされてないTypeScriptのバージョンを利用する場合)は、以下のように型を定義することでNonWidening Literal Typesと同じ挙動を期待することができます。

const hoge: "HOGE" = "HOGE";

まとめ

ここらへんはTypeScript独自色がでている部分だなと感じました。

他の静的型付け言語で似たような仕様のものってあるのでしょうか...

型が意図せぬ挙動するようならばこのような点を重点的に考えてみたいです。

以上です。