soranoba
soranoba Author of soranoba.net
programming

runtypesでenumの型を表現する

外の世界のデータをTypeScriptの世界に持ってくる際に、型チェックを行うruntypesというライブラリがあります。
この記事はruntypesでenumを表現する方法について纏めたものです。

Literalで表現する

1つ目の方法はLiteralを用いて、TypeScriptのenumを使用せずに、Union型として表現する方法です。
当然ながら、この型をswitch文などで判定する際にLiteralを毎回記述する必要があります。

import * as r from "runtypes";

export const ChartDataType = r.Union(
  r.Literal("twitter_followers"),
  r.Literal("twitter_followings"),
  r.Literal("twitter_tweets"),
  r.Literal("twitter_listed"),
);
export type ChartDataType = r.Static<typeof ChartDataType>;

withConstraintで表現する

2つ目の方法はUnknown.withConstraintを使用する方法です。

import * as r from "runtypes";

const Enum = <EnumType>(e: Record<string, EnumType>): r.Runtype<EnumType> => {
  const values = Object.values<unknown>(e);
  const name = values.map((x) => JSON.stringify(x)).join(" | ");
  return r.Unknown.withConstraint<EnumType>((v) => values.includes(v), {name});
}

export enum ChartDataType {
  TwitterFollowers = "twitter_followers",
  TwitterFollowings = "twitter_followings",
  TwitterTweets = "twitter_tweets",
  TwitterListed = "twitter_listed",
}
export type ChartDataRuntypes = Enum(ChartDataType);

Unknown.withConstraintは型が正しいかを関数で表現するものです。
Literalを用いた場合に近い出力が得られるように、nameを指定していますが必須ではありません。

こちらの方法だとTypeScriptのenumをそのまま利用することができますが、enum名とtype名が同じ場合は衝突するので異なる名称をつける必要があります。

参考文献

(Updated: )

comments powered by Disqus