我有一个方法将一个对象作为输入,该对象的值是字符串数组;它返回一个对象,其值是键等于字符串值的对象。例如:
myFunction({foo: ['a', 'b']}) // ==> {foo: {a: Widget, b: Widget}}
我正在尝试定义此功能的签名。我最好的尝试是:
declare function myFunction
<Q extends string[], T extends {[key: string]: Q}>
(keys: T) : {[key1 in keyof T]: {[key2 in T[key1][number]]: Widget}}
此几乎起作用,除了不推断嵌套对象的键名。第一个示例返回:
{
foo: {
[x: string]: Widget;
};
}
我想让它返回
{
foo: {
a: Widget;
b: Widget;
};
}
可以做到吗?
如果您的数组始终只包含"a"
和"b"
,则可以定义字符串文字的并集类型:
type MyUnionType = "a" | "b"
然后将变量foo
定义为MyUnionType[]
。结果是:
declare function myFunction
<Q extends MyUnionType[], T extends {[key: string]: Q}>
(keys: T) : {[key1 in keyof T]: {[key2 in MyUnionType]: Widget}}
应该工作:)
但是如果您的数组总是由不同的字符串组成,那么就不可能实现这种类型的输入,因为TypeScript只是设计时工具
为了允许TS修复推论,我们需要为数组键成员添加其他通用类型:
declare function myFunction
<Q extends K[], T extends {[key: string]: Q}, K extends string>
(keys: T): { [key1 in keyof T]: { [key2 in T[key1][number]]: Widget } }
[请注意Q extends K[]
,我们现在说的是Q
不是string[]
,而是K[]
,这意味着TS将把数组的成员缩小为比字符串更具体的类型。