typescript - 键入一组泛型推断类型

标签 typescript generics nested type-inference inference

我正在尝试创建对象数组的类型。该对象的第一个和第二个键需要匹配。例如:

[{ 
  key1: "hi",
  key2: "world"
},{
  key1: 1,
  key2: 2
},{
  key1: true,
  key2: false
}]
这是我想出的,但它并不完全有效。我有一个通用类型来定义数组中的对象。调用它生成数组类型时,会引发错误。
type ArrayItem<T> = {
  key1: T,
  key2: T
}

// This raises an error Generic Type ArrayItem requires 1 type argument
type Array = ArrayItem<T>[]
键入这样的嵌套对象的最佳方法是什么(具有类型推断支持)?

最佳答案

如果您没有 T 的可能类型的有限列表在 ArrayItem<T> , TypeScript 中没有具体的类型对应于 Array<ArrayItem<T>> .将这样的东西表示为非泛型类型需要像 existential types 这样的东西。 ,TypeScript 不直接支持。
(如果您确实有一个有限列表,例如 ArrayItem<string> | ArrayItem<number> | ArrayItem<boolean> ,那么您可以像在另一个答案中一样使用联合。)
在 TypeScript 中,最接近此的是泛型类型,在推理和编译器警告方面,最好的做法是将其表示为类似 generic constraint 的内容。 .
一种方法是编写一个通用的辅助函数 asMyArray()接受 tuple ,编译器将检查元组的每个元素以确保它满足约束。一个障碍是 {key1: "hi", key2: 2}如果您允许诸如 string | number 之类的内容,则确实满足约束条件如 T .为了防止编译器愉快地接受所有类型对,我将尝试使其推断 T来自 key1仅(请参阅 microsoft/TypeScript#14829 以了解防止从特定推理站点进行推理的方法),然后只需检查 key2匹配:

type NoInfer<T> = [T][T extends any ? 0 : 1]

const asMyArray = <T extends readonly any[]>(
    x: [...({ [K in keyof T]: { key1: T[K], key2: NoInfer<T[K]> } })]) =>
    x;
泛型类型参数 T是对应于 key1 的元组传入数组的每个元素的值。传入的数组,x , 是 mapped tuple type . & {}位降低 key2 的推理优先级. [... ] bit 只是提示编译器推断一个元组而不是一个数组(它无法区分不同的元素),让我们测试一下:
const myArray = asMyArray([{
    key1: "hi",
    key2: "world"
}, {
    key1: 1,
    key2: 2
}, {
    key1: true,
    key2: false
}])
// const asMyArray: <[string, number, boolean]>(...)
你可以看到 T推断为 [string, number, boolean] .这成功了,而以下内容,其中 T以同样的方式推断,失败:
const badArray = asMyArray([{
    key1: "hi", key2: 123 // error!
    // -------> ~~~~
    // number not assignable to string
}, {
    key1: 1, key2: "world" // error!
    // ----> ~~~~
    // string not assignable to number
}, {
    key1: true, key2: false
}]);
看起来像你想要的。好的,希望有帮助;祝你好运!
Playground link to code

关于typescript - 键入一组泛型推断类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62487613/

相关文章:

javascript - 使用计算的 aurelia 搜索过滤在渲染 View 时会导致问题

node.js - Node 和 Angular 与 TypeScript

c# - 在 C# 中,Type.FullName 何时返回 null?

scala - 在 Scala 中避免深度嵌套的 Option 级联

ruby - 执行嵌套 for 循环的最不冗长的方法是什么?

node.js - typescript 和 Jest : Avoiding type errors on mocked functions

javascript - 后续变量声明必须具有相同的类型

java - hashmap 中的 <K, V> 是什么,我如何在我自己的类中使用它?

java - 如何对具有实现相同接口(interface)的不同对象的列表进行排序?

java - MapStruct嵌套对象,仅当源元素不为null时创建目标对象