JavaScript/TypeScriptメモ

TypeScriptでPhantomType(幽霊型)を実装する3つのパターン

TypeScriptでPhantomType(幽霊型)を実装する3つのパターン

TypeScriptで幽霊型を実装するパターンをまとめました。

すべて、**元の「プリミティブ」に「形式的にオブジェクトを付加する」**ことで幽霊型を実現しています。

1. {unique symbol: never}

declare const P1_1US: unique symbol;
type P1_1 = string & { [P1_1US]: never };

declare const P1_2US: unique symbol;
type P1_2 = string & { [P1_2US]: never };

const P1func = (p: P1_1): void => {};

P1func('aaa'); //エラー
P1func('aaa' as P1_1); //OK
P1func('aaa' as P1_2); //エラー

メリット

型として一番綺麗?

デメリット

1つ1つの方ごとに、unique symbolを定義しないといけないので、面倒

2. {unique symbol: string}

declare const P2: unique symbol;
type P2_1 = string & { [P2]: 'P2_1'};
type P2_2 = string & { [P2]: 'P2_2'};

const P2func = (p: P2_1): void => {};

P2func('aaa'); //エラー
P2func('aaa' as P2_1); //OK
P2func('aaa' as P2_2); //エラー

メリット

unique symbolの定義が1つだけで済む

デメリット

ユニークな文字列を振らないといけない(「P2_1」「P2_2」の部分)

3. {string: never}

type P3_1 = string & { __P3_1__: never};
type P3_2 = string & { __P3_2__: never};

const P3func = (p: P3_1): void => {};

P3func('aaa'); //エラー
P3func('aaa' as P3_1); //OK
P3func('aaa' as P3_2); //エラー

メリット

定義が楽

デメリット

ユニークな文字列を振らないといけない(「__P3_1__」「__P3_2__」の部分)