更新时间:2022-12-14 20:10:42
如果在 ArrayItem< T>
中没有 T
可能类型的有限列表,TypeScript中没有与 Array< ArrayItem< T>>>
相对应的具体类型.要将此类事物表示为非通用类型,将需要类似现有类型之类的东西,TypeScript不直接支持.
If you don't have a finite list of possible types for T
in ArrayItem<T>
, there's no concrete type in TypeScript corresponding to Array<ArrayItem<T>>
. To represent such a thing as a non-generic type would require something like existential types, which TypeScript doesn't directly support.
(如果您有一个有限列表,例如 ArrayItem< string> | ArrayItem< number> | ArrayItem< boolean>
,那么您可以像这样使用联合在另一个答案中.)
(If you do have a finite list, like ArrayItem<string> | ArrayItem<number> | ArrayItem<boolean>
, then you can just use a union like in the other answer.)
您在TypeScript中最接近的是通用类型,就推断和编译器警告而言,您将要做的***是将其表示为类似
The closest you can come to this in TypeScript is as a generic type, and the best you'll do in terms of inference and compiler warnings will be to represent this as something like a generic constraint.
执行此操作的一种方法是编写一个通用的辅助函数 asMyArray()
,该函数接受 确实满足约束.数字作为 T
.为了防止编译器愉快地接受所有类型对,我将尝试使它仅从 key1
推断 T
(请参阅
One way to do this is to write a generic helper function asMyArray()
accepting a 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 to see ways to prevent inferring from a particular inference site), and then just check that key2
matches that:
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
是
The generic type parameter T
is a tuple corresponding to the key1
values for each element of the passed-in array. The passed-in array, x
, is of a mapped tuple type. The & {}
bit lowers the inference priority of key2
. The [... ]
bit just prompts the compiler to infer a tuple and not an array (where it wouldn't be able to tell the different elements apart), Lets test it out:
const myArray = asMyArray([{
key1: "hi",
key2: "world"
}, {
key1: 1,
key2: 2
}, {
key1: true,
key2: false
}])
// const asMyArray: <[string, number, boolean]>(...)
您会看到 T
被推断为 [字符串,数字,布尔值]
.此操作成功,而通过相同的方式推断 T
的以下操作失败:
You can see that T
is inferred as [string, number, boolean]
. This succeeds, while the following, in which T
is inferred the same way, fails:
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
}]);
看起来像您想要的.好的,希望能有所帮助;祝你好运!
Looks like what you want. Okay, hope that helps; good luck!