さまざまな種類のグラフの生成を担当するサービスがあります。
生成できるグラフのスペースには2つの次元がchartType
ありdataType
、は両方とも有限の値のセットであり、次のようになります。
enum ChartType {
ChartTypeA,
ChartTypeB,
ChartTypeC
}
enum DataType {
DataTypeA,
DataTypeB,
DataTypeC
}
このサービスは、単一のパブリックメソッドを公開しgenerateChart(chartType: ChartType , dataType: DataType)
ます。このメソッドchartType
は、渡される内容に応じて、関連するプライベートメソッドを呼び出します。
プライベートメソッドの正確な実装は、他のパラメータに依存しますdataType
。
ここまでは順調ですね。
私の問題は次のとおりです。いくつかの組み合わせは(ChartType, DataType)
不可能です(つまり、ChartTypeA
とでグラフを生成できませんDataTypeC
)。これにより、現在の実装に疑問が生じます。
可能なパラメーターのペアのみが関数に渡されるようにコンパイラーが強制できるように、データを整理するためのより良い方法は何ですか?
可能な有効な組み合わせごとにオーバーロードを使用できます。
enum ChartType {
ChartTypeA,
ChartTypeB,
ChartTypeC
}
enum DataType {
DataTypeA,
DataTypeB,
DataTypeC
}
function generateChart(chartType: ChartType.ChartTypeA, dataType: DataType.DataTypeA)
function generateChart(chartType: ChartType.ChartTypeC, dataType: DataType.DataTypeC)
function generateChart(chartType: ChartType.ChartTypeB, dataType: DataType.DataTypeB)
function generateChart(chartType: ChartType, dataType: DataType) { // Implementation signature
}
generateChart(ChartType.ChartTypeA, DataType.DataTypeA)
generateChart(ChartType.ChartTypeA, DataType.DataTypeC) // Error
または、マッピングタイプを使用して、式を少し減らすことができます。
interface EnuMap {
[ChartType.ChartTypeA]: DataType.DataTypeA,
[ChartType.ChartTypeB]: DataType.DataTypeB,
[ChartType.ChartTypeC]: DataType.DataTypeC,
}
function generateChart<T extends ChartType>(chartType: T, dataType: EnuMap[T])
function generateChart(chartType: ChartType, dataType: DataType) { // Implementation signature
}
generateChart(ChartType.ChartTypeA, DataType.DataTypeA)
generateChart(ChartType.ChartTypeA, DataType.DataTypeC) // Error
注マッピングタイプにインターフェイスを使用する場合、プラグインがタイプの新しい組み合わせをサポートしている場合など、必要に応じてインターフェイスを拡張できます。
編集
ほとんどの組み合わせが可能であり、少数のみを除外する必要がある場合は、別のアプローチを使用できます。最初に、パラメーターのすべての可能な組み合わせとExclude
、不可能な組み合わせを取り除くための使用を含むタイプを作成します。
function generateChart<T extends Excluded>(...a: T)
function generateChart(chartType: ChartType, dataType: DataType) { // Implementation signature
}
type AllCombinations = {
[C in ChartType]: {
[D in DataType]: [C, D]
}
}[ChartType][DataType]
// Exclude unwanted combinations
type Excluded = Exclude<AllCombinations, [ChartType.ChartTypeA, DataType.DataTypeC]>;
generateChart(ChartType.ChartTypeA, DataType.DataTypeA)
generateChart(ChartType.ChartTypeB, DataType.DataTypeA)
generateChart(ChartType.ChartTypeA, DataType.DataTypeC) // Error
このアプローチでは、パラメーター名の表現力が少し失われ、コンパイラーが提案するオーバーロードが発生します(コード補完だけで、期待どおりに機能します)
インテリセンスでより適切に機能し、パラメーター名を保持するソリューションはUnionToIntersection
、ここから使用して構築できます。最初にすべての可能なシグニチャの和集合を作成し、次にUnionToIntersection
すべてのオーバーロードを含む関数を作成するために使用します。
type AllCombinations = {
[C in ChartType]: {
[D in DataType]: [C, D]
}
}[ChartType][DataType]
type Excluded = Exclude<AllCombinations, [ChartType.ChartTypeA, DataType.DataTypeC]>;
type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never
type SignatureHelper<T> = T extends [infer C, infer D] ? (chartType: C, dataType: D) => void : never;
type GenerateChartType = UnionToIntersection<SignatureHelper<Excluded>>
const generateChart:GenerateChartType = (chartType: ChartType, dataType: DataType) => { // Implementation signature
}
generateChart(ChartType.ChartTypeA, DataType.DataTypeA)
generateChart(ChartType.ChartTypeB, DataType.DataTypeA)
generateChart(ChartType.ChartTypeA, DataType.DataTypeC) // Error
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加