LoginSignup
2
3

More than 5 years have passed since last update.

TypeScript 2.5.3 での疑似文字列 enum の書き方

Last updated at Posted at 2017-10-14

あれこれ試した結果、 const インスタンスを作って Mapped Types で型付けする方法に落ち着きました。

export type StringEnumAdapter<T> = { readonly [K in keyof T]: keyof T };

const FooKeyRaw = {
  ITEM_1: 'ITEM_1',
  ITEM_2: 'ITEM_2',
  ITEM_3: 'ITEM_31', // こういうミスは通ってしまう
};
export type FooKeyType = keyof typeof FooKeyRaw;
export const FooKey = FooKeyRaw as StringEnumAdapter<typeof FooKeyRaw>;

// これは (TypeScript 2.5.3 では) NG
const aKey: FooKeyType = FooKeyRaw.ITEM_1;

// これは OK
const bKey: FooKeyType = FooKey.ITEM_1;
console.log(bKey);

// これは NG
const cKey: FooKeyType = FooKey.NOT_EXIST;

// これも NG
FooKey.ITEM_1 = 'ITEM_2';

// ITEM_31
console.log(FooKey.ITEM_3);

その他の方法

namespace + export const

TypeScriptでのイベント名を管理・指定するもう一つの方法(+ストリングリテラル型にも対応)
https://qiita.com/ConquestArrow/items/02826db3ddbe98d280bd

class の static メンバ

TypeScriptでのイベント名をclickで指定するのはもう辞めよう
https://qiita.com/tonkotsuboy_com/items/b32801246ec14f444514

const でキーだけ宣言して関数で初期化

typo 等でキーと値が乖離するミスは防げます。が、2017-10-15 現在、uglifyjs-webpack-plugin を通してもコンパイル時解決されないので実行コストが...

declare global {
  interface ObjectConstructor {
    keys<T>(t: T): Array<keyof T>;
  }
}

export type StringEnumAdapter<T> = { readonly [K in keyof T]: keyof T };
type StringEnumAdapterMutable<T> = { [K in keyof T]: keyof T };

export function asStringEnum<T>(t: T): StringEnumAdapter<T> {
  const tt = t as any as StringEnumAdapterMutable<T>;
  for (const k of Object.keys(tt)) {
    tt[k] = k;
  }
  return tt;
}

const BarKeyRaw = {
  BAZ: null,
  CUX: null,
};
export type BarKeyType = keyof typeof BarKeyRaw;
export const BarKey = asStringEnum(BarKeyRaw);

// これは OK
const aaKey: BarKeyType = BarKey.BAZ;

// BAZ
console.log(aaKey);

// これはNG
const bbKey: BarKeyType = 'BAZOOKA';

// これもNG
BarKey.BAZ = BarKey.CUX;
2
3
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
3