arrays - 将元组类型转换为新类型
问题描述
我可以编写以下代码并且它可以工作:
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] {
但它不会编译错误
剩余元素类型必须是数组类型。
我该如何解决?
解决方案
该语法[H, ...T]
已提出但不受支持。对rest/spread位置的元组的支持使我们可以像这样表示相同的概念:
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
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
}
推荐阅读
- python - 如何在python中创建子模块?感谢
- presto - 子查询在 presto
- json - 使用 Gatsby 循环播放来自 Tumblr API 的 JSON 图像
- python - 线被 matplotlib 的曲面图遮挡
- ruamel.yaml - 解析带有冒号的标量的列表时出现 ScannerError
- azure - 如何将 azure cli list 命令的值放入变量中?
- python - 是否有与 dropwizard 指标等效的 python?
- php - PhpOffice\PhpSpreadsheet 从 excel 错误字符集中导入 mysql
- css - CSS 媒体无法在一组设备上运行
- asp.net - 在没有 Internet 连接的 Web 服务器上启用 Azure AD SSO