Typescript 定义强制共享值的元组列表

Typescript 定义强制共享值的元组列表,typescript,ecmascript-6,Typescript,Ecmascript 6,我想指定一种类型,强制前一个元组中的最后一个值与下一个元组中的第一个值匹配,即: 常量连续间隔:三个连续间隔=[ [0, 1], [1, 2], [2, 3], ]; 我已经非常接近于以下定义: type IntervalMin=[number,TEnd]; 键入IntervalMax=[TStart,number]; 类型间隔=[TStart,TEnd]; 类型三连续间隔=[ 数字区间, 数值区间, 数值区间 ]; 这是可行的,但我必须传递泛型签名中的值: //有效! const foo:

我想指定一种类型,强制前一个元组中的最后一个值与下一个元组中的第一个值匹配,即:

常量连续间隔:三个连续间隔=[
[0, 1],
[1, 2],
[2, 3],
];
我已经非常接近于以下定义:

type IntervalMin=[number,TEnd];
键入IntervalMax=[TStart,number];
类型间隔=[TStart,TEnd];
类型三连续间隔=[
数字区间,
数值区间,
数值区间
];
这是可行的,但我必须传递泛型签名中的值:

//有效!
const foo:三个连续间隔=[
[0, 2], [2, 3], [3, 4],
];
//如预期的那样中断
常数条:三个连续间隔=[
[0, 2], [3, 4], [4, 5],
^抛出错误:“类型“3”不可分配给类型“2”
];

如何让TypeScript推断泛型签名?

您的问题的答案是使用一个helper函数并依赖该函数中的类型参数推断,以及各种技巧,以使推断不会太宽(例如,您不希望您的
被推断为
三个连续间隔
,但它可能是)

但这也类似于,所以我不妨给出一个例子,我们支持任意长度的元组,而不是只支持长度为3的元组

您可以使用、和类型来表示所需的形状(一组数字对,其中每对的第二个元素与下一对的第一个元素的类型相同),作为对数组类型的约束。以下是一种方法:

// prepend a value to a tuple.  Cons<1, [2,3]> is [1,2,3]
type Cons<H, T extends any[]> = ((h: H, ...t: T) => any) extends
    ((...l: infer L) => any) ? L : never;

// verify that T is an array of numeric pairs where the last element of
// each pair is the same as the first element of the next pair
type VerifyContig<T> = T extends Array<any> ?
    { [K in keyof T]: [
        K extends '0' ? number :
        Cons<null, T> extends Record<K, [any, infer N]> ? N : never
        , number
    ] } : never;

// helper function to validate that values match the desired shape
const asContig = <N extends number, T extends [N, N][] | [[N, N]]>(
    contig: T & VerifyContig<T>
): T => contig;

asContig([]); // okay
asContig([[1, 2]]); // okay
asContig([[1, 2], [2, 3]]); // okay
asContig([[1, 2], [3, 4]]); // error!
//                 ~ <-- 3 is not assignable to 2
asContig([[1, 2], [2, 3], [3, 5], [5, 8], [8, 13]]); // okay
asContig([[1, 2], [2, 3], [3, 5], [5, 7], [8, 13]]); // error!
//            8 is not assignable to 7 --> ~
//在元组前加一个值。Cons是[1,2,3]
类型Cons=((h:h,…t:t)=>any)扩展
((…l:推断l)=>任何)?l:从不;
//验证T是一个数字对数组,其中
//每对都与下一对的第一个元素相同
类型VerifyContig=T扩展数组?
{[K in keyof T]:[
K扩展了“0”?编号:
犯罪扩大了记录?N:从来没有
数字
]}:从来没有;
//用于验证值是否与所需形状匹配的辅助函数
常量asContig=(
挫伤:T&VerifyContig
):T=>contig;
asContig([]);//好的
asContig([[1,2]]);//好的
asContig([[1,2],[2,3]]);//好的
asContig([[1,2],[3,4]]);//错误!
//                 ~  ~
看起来不错。希望对你有帮助;祝你好运