键入通用推断类型的数组
Typing an array of generic inferred types
我正在尝试创建对象数组的类型。此对象的第一个和第二个键必须匹配。例如:
[{
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>[]
键入这样的嵌套对象的最佳方法是什么(支持类型推断)?
处理数组可能会很麻烦,即使使用泛型类型也是如此。这在很大程度上取决于初始化数组后如何使用您的项目。根据您的代码片段,我将开始为数组中的每个“种类”条目创建接口,以便为每个不同的属性集获得强类型。
export interface FooItemType {
key1: string,
key2: string,
}
export interface BarItemType {
key1: boolean,
key2: boolean,
}
然后,您可以创建一个新类型来映射您之前定义的接口。
export type ItemType = BarItemType | FooItemType;
之后,您可以将其声明为简单的 ItemType
数组。
export myArr: ItemType[] = [{
key1: "hi",
key2: "world"
},{
key1: 1,
key2: 2
},{
key1: true,
key2: false
}]
虽然这种方法是强类型的,但在您从数组中获取 myArray[i]
项后可能会导致一些手动转换。有时我们在考虑“类型”在应用程序中的使用之前就设计了它,因此设计数据结构时必须从整体上寻找它。
如果您没有 ArrayItem<T>
中 T
的可能类型的有限列表,则 TypeScript 中没有对应于 Array<ArrayItem<T>>
的具体类型。要将这样的东西表示为非泛型类型,需要类似 existential types 的东西,TypeScript 不直接支持它。
(如果你做有一个有限列表,比如ArrayItem<string> | ArrayItem<number> | ArrayItem<boolean>
,那么你可以像其他答案一样使用联合。)
在 TypeScript 中,您最接近的是作为泛型类型,在推理和编译器警告方面,您最好将其表示为类似 generic constraint 的东西。
一种方法是编写一个通用的辅助函数 asMyArray()
接受 tuple, and the compiler will check each element of the tuple to make sure it meets the constraint. One snag is that {key1: "hi", key2: 2}
does meet the constraint if you allow things like string | number
as T
. To prevent the compiler from happily accepting all pairs of types, I will try to make it infer T
from key1
only (see 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
的推理优先级。 [... ]
位只是提示编译器推断一个元组而不是一个数组(它无法区分不同的元素),让我们测试一下:
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
}]);
看起来像你想要的。好的,希望有所帮助;祝你好运!
我正在尝试创建对象数组的类型。此对象的第一个和第二个键必须匹配。例如:
[{
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>[]
键入这样的嵌套对象的最佳方法是什么(支持类型推断)?
处理数组可能会很麻烦,即使使用泛型类型也是如此。这在很大程度上取决于初始化数组后如何使用您的项目。根据您的代码片段,我将开始为数组中的每个“种类”条目创建接口,以便为每个不同的属性集获得强类型。
export interface FooItemType {
key1: string,
key2: string,
}
export interface BarItemType {
key1: boolean,
key2: boolean,
}
然后,您可以创建一个新类型来映射您之前定义的接口。
export type ItemType = BarItemType | FooItemType;
之后,您可以将其声明为简单的 ItemType
数组。
export myArr: ItemType[] = [{
key1: "hi",
key2: "world"
},{
key1: 1,
key2: 2
},{
key1: true,
key2: false
}]
虽然这种方法是强类型的,但在您从数组中获取 myArray[i]
项后可能会导致一些手动转换。有时我们在考虑“类型”在应用程序中的使用之前就设计了它,因此设计数据结构时必须从整体上寻找它。
如果您没有 ArrayItem<T>
中 T
的可能类型的有限列表,则 TypeScript 中没有对应于 Array<ArrayItem<T>>
的具体类型。要将这样的东西表示为非泛型类型,需要类似 existential types 的东西,TypeScript 不直接支持它。
(如果你做有一个有限列表,比如ArrayItem<string> | ArrayItem<number> | ArrayItem<boolean>
,那么你可以像其他答案一样使用联合。)
在 TypeScript 中,您最接近的是作为泛型类型,在推理和编译器警告方面,您最好将其表示为类似 generic constraint 的东西。
一种方法是编写一个通用的辅助函数 asMyArray()
接受 tuple, and the compiler will check each element of the tuple to make sure it meets the constraint. One snag is that {key1: "hi", key2: 2}
does meet the constraint if you allow things like string | number
as T
. To prevent the compiler from happily accepting all pairs of types, I will try to make it infer T
from key1
only (see 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
的推理优先级。 [... ]
位只是提示编译器推断一个元组而不是一个数组(它无法区分不同的元素),让我们测试一下:
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
}]);
看起来像你想要的。好的,希望有所帮助;祝你好运!