LoginSignup
2
0

More than 3 years have passed since last update.

TypeScriptのenumを型変数として受けて制約を加えたい時の方法

Last updated at Posted at 2021-01-07

結論

数値enumは extends number, 文字列enumは extends string すればよい

function F2<Collection extends string | undefined>(item: Collection) {
    return item;
}
F2<Colors | undefined>(undefined);
F2<Colors | undefined>(Colors.Blue);

(TypeScript version: v4.1.3)

前提

TypeScript で enum 型を使うべきでなく union type を使うべきなのは承知しています。
参考: https://www.kabuku.co.jp/developers/good-bye-typescript-enum

それでもライブラリの兼ね合いなどでenumに依存せざるを得ないため、enumでの型の挙動を調べたメモになります。

enumの挙動についてはこちらの記事が相当詳しかったです。
https://2ality.com/2020/01/typescript-enums.html

実験

文字列enumと数値enumを用意します

export enum Colors {
    Red = 'red',
    Green = 'green',
    Blue = 'blue',
}

export enum Numbers {
    One = 1,
    Two = 2,
}

とりあえず型変数で受けてみます

function F1<Collection>(item: Collection) {
    return item;
}

// 数値enumでは strict check にならない
F1<Numbers>(Numbers.One); // ok
F1<Numbers>(1); // よくないことにok(なので数値enumは非常に使うべきでない)

// 文字列enum で strict check ができる
F1<Colors>(Colors.Red); // ok
F1<Colors>('blue'); // error
// Argument of type '"blue"' is not assignable to parameter of type 'Colors'.

本題。これに制約を加えます。
単純に undefined も指定できるようにしてみます。

function F2<Collection extends string | undefined>(item: Collection) {
    return item;
}

F2<Colors>(Colors.Blue); // ok
F2<Colors>(undefined); // これは単に型変数の指定が間違っている
// Argument of type 'undefined' is not assignable to parameter of type 'Colors'.(2345)

F2<Colors | undefined>(undefined); // ok
F2<Colors | undefined>(Colors.Blue); // ok
F2<Colors | undefined>('blue'); // error
// Argument of type '"blue"' is not assignable to parameter of type 'Colors | undefined'.(2345)

// ↓2つはもちろんだめ
F2<Colors | undefined>(1); // error
F2<Numbers | undefined>(1); // error

というわけで extends string すれば文字列enumを受けることができるみたいです。

一応数値enumのほうも置いておきます。

function F3<Collection extends number | undefined>(item: Collection) {
    return item;
}

F3<Numbers | undefined>(Numbers.One); // ok 
F3<Numbers | undefined>(undefined); // ok 
F3<Numbers | undefined>(1); // よくないことにこれも通る
F3<Numbers | undefined>('hoge'); // error
// Argument of type '"hoge"' is not assignable to parameter of type 'Numbers | undefined'.(2345)

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0