【 TypeScript 】文字列リテラル型と文字列型のユニオン型を作成する

Typescriptで型を作成するときに、'dog' や 'cat' のような特定の文字列をリテラル型として指定しつつ、その他の文字列型も含める方法について考えます。

単純に次のような型を考えてみましょう。

type AnimalWithString = 'dog' | 'cat' | string
// type Animal = string

この場合、Animalの型情報はtype Animal = stringとなってしまい、dogcat の情報が失われてしまいます。これでは役に立ちません。

stringを取り除いてみます。

type Animal = 'dog' | 'cat'
// type Animal = "dog" | "cat"
const myAnimal:Animal = 'bird'
//Type '"bird"' is not assignable to type 'Animal'.(2322)

これだとただのリテラル型のユニオンになってしまい、birdといった他の文字列を受け入れられません。

そこでテクニックを1つ使います。

stringのかわりに(string & {})を使用します。

type AnimalSpecified = 'dog' | 'cat' | (string & {})
// type AnimalSpecified = "dog" | "cat" | (string & {})
const animalIncludingMightBe:AnimalSpecified = 'bird'

これでdogcat を維持したまま、string型の情報も提供されるので、文字列リテラル型と文字列型のユニオン型の両方をもった型を作成できたことになります。

TS Playgroundで実際の挙動を確認してみてください。

(string & {}) において、{}非-null 非-undefined な型を指します。&を使ってstringとのIntersect型をつくることで、TypeScriptはstring型を維持することができます。

こちらのStackoverFlowの質問と回答で、今回の方法を知りました。

他に良い方法があれば教えて下さい。

以上です。