Синтаксис [H, ...T]
был , предложен , но не поддерживается. Поддержка кортежей в позициях покоя / спреда позволяет нам вместо этого представлять такую же концепцию:
type Cons<H, T extends readonly any[]> =
((h: H, ...t: T) => void) extends ((...r: infer R) => void) ? R : never;
Observe:
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
. Это трюк , который намекает компилятору, что вы хотите, чтобы тип map
был выведен как кортеж, если это возможно . В противном случае, когда вы используете литерал массива, такой как ["a", 1]
, это будет означать Array<string | number>
, а не [string, number]
. Поскольку ваша cases()
функция довольно сильно зависит от предвосхищения кортежа, полезно, если компилятор выведет для вас кортежи. Это может быть причиной того, что у вас возникли проблемы с этой работой? Но даже без этого вы можете использовать const
утверждений или другие аннотации, чтобы ваши свойства 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
}