考虑下一个示例:
enum Keys {
A = 'a',
B = 'b',
C = 'c',
}
//imagine a lot more possible keys
type ExtendKeysPropsByKey = {
[Keys.A]: {
a: string
}
[Keys.B]: {
b: string
}
}
//Keys.C doesn't require extended props
type KeysPropsByKey = {
[key in keyof Keys]: {
key: key
} & ExtendKeysPropsByKey[key]
//errors: Type 'key' cannot be used to index type 'ExtendKeysPropsByKey'.
//also tried:
//ExtendKeysPropsByKey[key] ? ExtendKeysPropsByKey[key] : {}
//ExtendKeysPropsByKey[key] || {}
//key in keyof ExtendKeysPropsByKey ? ExtendKeysPropsByKey[key] : {}
//neither works
}
因此,假设有50种可能的Keys
,我们想创建一个类型,该类型最初包含一个key
实际值的Keys
道具,并且希望能够(可选)扩展道具,因此上述示例的预期类型为:
{
[Keys.A]: {
key: Keys.A
a: string
}
[Keys.B]: {
key: Keys.B
b: string
}
[Keys.C]: {
key: Keys.C
}
}
任何可能的情况?
答案 0 :(得分:2)
希望我能满足您的要求:)。因此,我制作了一个带有两个参数的类型构造函数-Keys
-它定义了我们将拥有的键,KeyProps
-类型代表了给定键应具有的道具。
enum Keys {
A = 'a',
B = 'b',
C = 'c',
}
type ExtendKeysPropsByKey = {
[Keys.A]: {
a: string
}
[Keys.B]: {
b: string,
c: number;
}
}
type MakeT<Keys extends string, KeyProps extends Partial<Record<Keys, any>>> = {
[K in Keys]: {key: K} & (K extends keyof KeyProps ? KeyProps[K] : {})
}
type Result = MakeT<Keys, ExtendKeysPropsByKey>
/**
type Result = {
a: {
key: Keys.A;
} & {
a: string;
};
b: {
key: Keys.B;
} & {
b: string;
c: number;
};
c: {
key: Keys.C;
};
}
*/
说明:
KeyProps extends Partial<Record<Keys, any>>
我们将第二个参数定义为具有所需键的记录,但由于不是我们需要的所有键,它也是局部的。{key: K} & (K extends keyof KeyProps ? KeyProps[K] : {})
我们说给定键的值将具有key
等于键的属性,并且将其与KeyProps
对象中给出的道具相交