且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

键入通用推断类型的数组

更新时间: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!

游乐场连结代码