Boilerplateのない同じタイプスクリプトenum間のマッピング
8954 ワード
型紙のenumsは変です.彼らは、構造/ダックタイピングパターンに従わないTS(私が気づいている限り)の唯一の部分です.文字列の代わりにenumを好むなら、以下のようにしてください.
あなたは同じメンバーを含む2つのenumを持っています、しかし、TSは互換性があると理解しません.今、私は3つの主要なパターンが問題を解決するために利用するのを見ます:
IDCのapproach:あなたはどこでキャスト.これは最も簡単ですが、それは危険です、enumのキャストとしては、ほとんど何かを行うことができます.
purist :型は異なっていますので、類似点を無視してマッパー関数(またはオブジェクト)を作成し、必要に応じて使用します.
これは確かに非常に安全ですが、メンテナンスオーバーヘッドの多くを追加し、noooootのためのコード(バンドル)サイズがたくさんの理由がたくさん.
中間の地面:あなたは機能をつくりますが、中で投げられます.
一度だけキャストしたように、これは紙の上にアプローチ1よりもよく見えます、しかし、あなたは本当に同じ危険にさらされています:2つのenumsがどんな点ででも分岐するならば、あなたはTSから一つの警告を得ません.
私は、私たちがなんとか1/2のタイプ安全性を得ることができると思いました、そして、また、どれくらいの純度と束サイズを保持しますか?それはわかる.
JSレベルでは、この3番目のアプローチは些細なことですが、マッパー機能は本質的です
だから今では“ちょうど”私たちは同一のenums間のマップを許可されていることを確認するためにTSの制約を追加する問題です.
私の現在の解決は、それが非常によく拡張されることができたけれども、単純(同じキーと値)enumsで単純に働きます.では、最初に対称なenumを定義しましょう.
ソースenum型. 宛先enum型.これは、タイプセーフティロジックのコアです.ソースのスーパーセットではないenumにマップしようとすると、この行はここで叫びます. マッパー関数に与えられた実際の入力値の型.それから、これは基本的に目的地タイプから対応する値を「引く」条件付声明で使われます.あなたが条件タイプで読む必要があるならばthe documentation . タイプレベルのマッピングが必要な場合は、上記の魔法を使用してください.
互換性のないenumは拒否されます.
このマジックを利用して、自動的にマッパー関数を生成する高次関数を作成する準備が整いました.
そしてこれです!今、あなたは電話ですべてのスイッチ文を置き換えることができます
スタックオーバーフローキーボードを持っている場合
ここでは完全なコード、およびTS Playground with examples :
あなたは同じメンバーを含む2つのenumを持っています、しかし、TSは互換性があると理解しません.今、私は3つの主要なパターンが問題を解決するために利用するのを見ます:
IDCのapproach:あなたはどこでキャスト.これは最も簡単ですが、それは危険です、enumのキャストとしては、ほとんど何かを行うことができます.
purist :型は異なっていますので、類似点を無視してマッパー関数(またはオブジェクト)を作成し、必要に応じて使用します.
これは確かに非常に安全ですが、メンテナンスオーバーヘッドの多くを追加し、noooootのためのコード(バンドル)サイズがたくさんの理由がたくさん.
中間の地面:あなたは機能をつくりますが、中で投げられます.
一度だけキャストしたように、これは紙の上にアプローチ1よりもよく見えます、しかし、あなたは本当に同じ危険にさらされています:2つのenumsがどんな点ででも分岐するならば、あなたはTSから一つの警告を得ません.
ボイラ板なしの安全性
私は、私たちがなんとか1/2のタイプ安全性を得ることができると思いました、そして、また、どれくらいの純度と束サイズを保持しますか?それはわかる.
JSレベルでは、この3番目のアプローチは些細なことですが、マッパー機能は本質的です
x => x
. だから今では“ちょうど”私たちは同一のenums間のマップを許可されていることを確認するためにTSの制約を追加する問題です.
実装
コア
私の現在の解決は、それが非常によく拡張されることができたけれども、単純(同じキーと値)enumsで単純に働きます.では、最初に対称なenumを定義しましょう.
type SymmetricalEnum<TEnum> = {
[key in keyof TEnum]: key;
};
そして、ここでは、トリックです-マッピングの結果値が何であるかを定義することができます、これは本質的にその利点のすべてで、TSメタ言語レベルのマッピングをしています:type MapperResult<
TSourceEnumObj,
TDestEnumObj extends SymmetricalEnum<TSourceEnumObj>,
TSourceValue extends keyof TSourceEnumObj
> = TDestEnumObj extends { [key in TSourceValue]: infer TResult } ? TResult : never;
私たちには、3つの一般的なargsがあります:互換性のないenumは拒否されます.
マッパ関数の作成
このマジックを利用して、自動的にマッパー関数を生成する高次関数を作成する準備が整いました.
const createEnumMapperFunction =
<TSourceEnumObj, TDestEnumObj extends SymmetricalEnum<TSourceEnumObj>>(from: TSourceEnumObj, to: TDestEnumObj) =>
<TInput extends keyof TSourceEnumObj>(value: TInput) =>
value as MapperResult<TSourceEnumObj, TDestEnumObj, TInput>;
ここでは1つのエラーが含まれています.そしてこれです!今、あなたは電話ですべてのスイッチ文を置き換えることができます
createEnumMapperFunction
, または、上記のようなタイプセーフバージョンでキャストを置き換えます.非対称enumsまたは他のケースのサポートを追加するようなあなたのニーズに微調整すること自由に感じなさい.最終コード
スタックオーバーフローキーボードを持っている場合
ここでは完全なコード、およびTS Playground with examples :
type SymmetricalEnum<TEnum> = {
[key in keyof TEnum]: key;
};
type MapperResult<
TSourceEnumObj,
TDestEnumObj extends SymmetricalEnum<TSourceEnumObj>,
TSourceValue extends keyof TSourceEnumObj
> = TDestEnumObj extends { [key in TSourceValue]: infer TResult } ? TResult : never;
const createEnumMapperFunction =
<TSourceEnumObj, TDestEnumObj extends SymmetricalEnum<TSourceEnumObj>>(from: TSourceEnumObj, to: TDestEnumObj) =>
<TInput extends keyof TSourceEnumObj>(value: TInput) =>
value as MapperResult<TSourceEnumObj, TDestEnumObj, TInput>;
私はあなたがこの便利な日を見つける願っています.あなたがしたならば、コメントで私に知らせてください、そして、あなたが改善されたバージョンを造ったならば、私も知っていたいです.Reference
この問題について(Boilerplateのない同じタイプスクリプトenum間のマッピング), 我々は、より多くの情報をここで見つけました https://dev.to/marcelltoth/mapping-between-identical-typescript-enums-without-the-boilerplate-5b28テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol