gpt4 book ai didi

typescript - 定义具有可选的第一个和最后一个元素的元组列表

转载 作者:搜寻专家 更新时间:2023-10-30 21:33:20 24 4
gpt4 key购买 nike

我正在尝试在 TypeScript 中对一些数据建模,如下所示:

// Sometimes we lookup the min/max dynamically, so we have keywords for them.
const intervalA: NumericInterval = [['$min', 3], [3, 5], [5, '$max']];

// Other times, we know the min/max and provide them inline
const intervalB: NumericInterval = [[0, 3], [3, 5], [5, 7]];

我尝试将 NumericInterval 定义为:

type MinInterval = ['$min', number];
type MaxInterval = [number, '$max'];
type Interval = [number, number];
type NumericInterval = [MinInterval?, ...Interval[], MaxInterval?];

但是,TypeScript 不喜欢它,因为 rest 元素必须在元组中放在最后

有没有更好的方式来表达这个模式?

最佳答案

据我所知,没有办法直接表示这种类型。它是具体类型的子类型 Array<["$min" | number, number | "$max"]> ,它太宽了,允许像 [[2, "$max"],[4, "$max"],["$min", 6]] 这样的东西.

可以使用generic , mapped , 和 conditional类型来表示所需的形状作为对数组类型的约束,但它相当丑陋/乏味/复杂,你必须使任何产生或接受该类型的东西都是通用的。我不妨展示一种方法,无需太多解释(如果您真的关心它或想使用此解决方案,我总是可以编辑更详尽的解释):

// get the tail of a tuple: Tail<[1,2,3]> is [2,3]
type Tail<L extends any[]> = ((...x: L) => any) extends
((h: any, ...t: infer T) => any) ? T : never;

// verify that T is a valid NumericInterval
type VerifyNumericInterval<T> = T extends Array<any> ?
{ [K in keyof T]: [
K extends '0' ? "$min" | number : number,
K extends keyof Tail<T> ? number : number | "$max"
] } : Array<["$min" | number, number | "$max"]>

// helper function to ensure parameter is a valid NumericInterval
const asNumericInteral = <T extends any[] | [any]>(
numericInterval: T & VerifyNumericInterval<T>
): T => numericInterval;

让我们测试一下:

asNumericInteral([]); // okay, zero length tuple
asNumericInteral([[1, 2]]); // okay
asNumericInteral([["$min", 2]]); // okay
asNumericInteral([[1, "$max"]]); // okay
asNumericInteral([["$min", "$max"]]); // okay, not sure if you want it to be
asNumericInteral([["$max", 2]]); // error!
// ~~~~~~ <-- string not assignable to never
asNumericInteral([[1, 2], [3, "$max"]]); // okay
asNumericInteral([["$min", 2], [3, "$max"]]); // okay
asNumericInteral([["$min", 2], [3, "$max"], [5, 6]]); // error!
// ~~~~~~ <-- string not assignable to number

这一切的行为都符合我对该类型的预期。顺便说一句,这仅对期望 NumericInterval 的函数的调用者有用。类型。具有泛型类型值的内部实现 T & VerifyNumericInterval<T>您可能必须自己处理边缘情况。编译器几乎不可能很好地推理未解析的泛型类型以注意到,比如说,以下内容:

function hmm<T>(numInt: T & VerifyNumericInterval<T>) {
for (let i = 0; i < numInt.length; i++) { // okay, numInt is known to be aray
const interval = numInt[i]; // interval is type [number | "$min", "$max" | number]
if (i !== 0) { // can't be "$min", right?
interval[0].toFixed(); // error?!
// but it has to be a number, why doesn't the compiler know it?!
}

// manually check
if ((i !== 0) && (typeof interval[0] === "number")) {
interval[0].toFixed(); // okay now
}
}
}

在那个函数中知道除了i === 0 , numInt[i]是一对,其中第一个元素肯定是 number .但是编译器无法弄清楚,所以你必须通过额外的检查(或使用类型断言)来帮助它。

好的,希望对你有帮助。祝你好运!

关于typescript - 定义具有可选的第一个和最后一个元素的元组列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56085340/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com