Насколько я знаю, нет способа представить этот тип напрямую. Это подтип конкретного типа Array<["$min" | number, number | "$max"]>
, который слишком широк и допускает такие вещи, как [[2, "$max"],[4, "$max"],["$min", 6]]
.
Вы можете использовать универсальные , сопоставленные и условные типы для представления желаемой формы в качестве ограничения на типы массивов, но это довольно уродливо / утомительно / сложно, и вам придется сделать все, что производит или принимает тип, универсальным. Я мог бы также показать один способ сделать это без особых объяснений (я всегда могу отредактировать более подробное объяснение, если вы действительно заботитесь об этом или хотите использовать это решение):
// 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
. Но компилятор не может понять это, поэтому вы должны пройти через дополнительные проверки (или использовать утверждения типа), чтобы помочь ему.
Хорошо, надеюсь, это поможет. Удачи!