TypeScript: 2番目のパラメーターの値を(1番目に基づいて)制限する方法
もし~のような定義があれば
type GroupIds = 'A'|'B'|'C'
type KeysA = 'A01' | 'A02'
type KeysB = 'B03' | 'B04'
type KeysC = 'C99'
それは次のように書けることは知っています
function MethodBy( p0:'A', p1:KeysA )
function MethodBy( p0:'B', p1:KeysB )
function MethodBy( p0:'C', p1:KeysC )
function MethodBy( p0, p1 )
{
//implement
}
でも、このようなものがあるかどうか聞きたいです
//maybe define a mapper
type IMapForKeys<T extends GroupIds> =
{
[ key: 'A' ]: KeysA
[ key: 'B' ]: KeysB
[ key: 'C' ]: KeysC
}
//then method can write like...
function MethodBy<T extends GroupIds>( p0:T, p1:IMapForKeys[T] )
{
//implement
}
それとも何か回避策はありますか、ヒントをもらえると嬉しいです、ありがとう :)
回答 #1
私が知っている最も近い方法は、GroupIds の値を手動で IMapForKeys のキーとして使用することです。
type GroupIds = 'A' | 'B' | 'C'
type KeysA = 'A01' | 'A02'
type KeysB = 'B03' | 'B04'
type KeysC = 'C99'
type IMapForKeys = {
'A': KeysA;
'B': KeysB;
'C': KeysC;
}
function MethodBy<T extends GroupIds>(p0: T, p1: IMapForKeys[T]) {}
MethodBy の使用意味は正しいです。
MethodBy('D', 'A01') // 'D' not allowed
MethodBy('A', 'A01') // allowed
MethodBy('A', 'B03') // 'B03' not allowed
もし新しいキーが GroupIds に追加されると、MethodBy の2番目のパラメータは Type 'T' cannot be used to index type 'IMapForKeys'. という型チェックに失敗します。
もし未知のキーが IMapForKeys に追加された場合、それを MethodBy の最初のパラメータとして使用することはできません。なぜなら、MethodBy は GroupIds のメンバーを必要とするからです。
可能であれば、型を再構築して、IMapForKeysからGroupIdsやKeysの型を引き出すようにすることをお勧めします。逆ではなく。これにより、型の信頼できる単一の情報源があるため、よりクリーンになると思います。
interface IMapForKeys {
'A': 'A01' | 'A02';
'B': 'B03' | 'B04';
'C': 'C99';
}
type GroupIds = keyof IMapForKeys
type KeysA = IMapForKeys['A']
type KeysB = IMapForKeys['B']
type KeysC = IMapForKeys['C']
function MethodBy<T extends GroupIds>(p0: T, p1: IMapForKeys[T]) {}
MethodBy('D', 'A01') // 'D' not allowed
MethodBy('A', 'A01') // allowed
MethodBy('A', 'B03') // 'B03' not allowed
回答 #2
考えられる解決策の一つは、識別ユニオンを使用することです。以下は例です:
type MyTypeA = {
p0: "A";
p1: 'A01' | 'A02';
}
type MyTypeB = {
p0: "B";
p1: 'B03' | 'B04';
}
type MyTypeC = {
p0: "C";
p1: 'C99';
}
function MethodBy(args: MyTypeA | MyTypeB | MyTypeC) {
//
}
//e.g.
MethodBy({ p0: "B", p1: "B04" }); //OK
MethodBy({ p0: "B", p1: "C99" }); //compile error
