我可以编写以下代码和it works:
function cases<K extends string, V, U, T>(map: { [key in K]: [V, U, T] }): [K, V, U, T][];
function cases<K extends string, V, U>(map: { [key in K]: [V, U] }): [K, V, U][];
function cases<K extends string, V>(map: { [key in K]: V }): [K, V][];
function cases<K extends string, V>(map: { [key in K]: V }) {
return Object.keys(map).map(key => ([key] as any[]).concat(map[key as K]) as any);
}
for (const [key, arr, res] of cases({
"abc": [[1, 2, "qqq"], 'qwe'],
"def": [[4, 5, "asd"], 'www'],
})) {
// const key: "abc" | "def"
// const arr: (string | number)[]
// const res: string
}
但是我不想写这堆重载:
function cases<K extends string, V, U, T>(map: { [key in K]: [V, U, T] }): [K, V, U, T][];
function cases<K extends string, V, U>(map: { [key in K]: [V, U] }): [K, V, U][];
function cases<K extends string, V>(map: { [key in K]: V }): [K, V][];
并想要指定一些元组类型:
function cases<K extends string, V extends any[]>(map: { [key in K]: V }): [K, ...V] {
休息元素类型必须是数组类型。
我该如何解决?
答案 0 :(得分:1)
语法[H, ...T]
为proposed,但不受支持。对tuples in rest/spread positions的支持使我们可以代表同样的概念:
type Cons<H, T extends readonly any[]> =
((h: H, ...t: T) => void) extends ((...r: infer R) => void) ? R : never;
观察:
type ConsTest = Cons<1, [2, 3, 4]> // [1, 2, 3, 4]
因此,您的cases()
函数可以这样输入:
function cases<K extends string, T extends any[]>(
map: { [key in K]: T | [] }
): Array<Cons<K, T>> {
return Object.keys(map).map(
key => ([key] as any[]).concat(map[key as K]) as any
);
}
这里,我们返回Array<Cons<K, T>>
,其中T
是map
参数属性中的数组类型。还要注意,在map
中,我使属性类型为T | []
,而不仅仅是T
。这是trick,它向编译器暗示您希望map
的类型为inferred as a tuple if possible。否则,当您使用["a", 1]
之类的数组文字时,通常会推断为Array<string | number>
而不是[string, number]
。由于您的cases()
函数在很大程度上依赖于添加到元组,因此,如果编译器为您推断出元组,则将很有帮助。这可能是您无法进行这项工作的原因吗?即使没有这个,您也可以使用const
assertions或其他注释来使map
属性成为元组。
好的,让我们确保它可以按您的意图工作:
for (const [key, arr, res] of cases({
"abc": [[1, 2, "qqq"], 'qwe'],
"def": [[4, 5, "asd"], 'www'],
})) {
key; // "abc" | "def"
arr; // (string | number) []
res; // string
}
是的,看起来不错。好的,希望能有所帮助;祝你好运!
for (const [key, arr, res] of cases({
"abc": [[1, 2, "qqq"], 'qwe'],
"def": [[4, 5, "asd"], 'www'],
})) {
key; // "abc" | "def"
arr; // (string | number) []
res; // string
}