2017-06-07 72 views
7

我想为其第一个元素是特定类型(例如Function)的数组定义一个类型,其余元素是空的类型。例如:在Typescript中,为第一个元素比其他元素更具体的数组定义一个类型

type FAs = [Function, {}, {}, {}, ...]; // pseudo code 

这样的事情可能吗?

的目的是提供一个单参数函数如下:

const myCaller = ([fun, ...args]: FAs) => fun.apply(args); 

另一种方法是使用两个参数来myCaller,像这样:

const myCaller = (fun: Function, args: any[]) => fun.apply(args); 

但出于美学原因我宁愿使用一个参数。我也怀疑类型系统是否支持什么可以说是任意长度的元组。也许这样的事情出于我不明白的计算机科学原因是不可取的。

+0

有点相关:https://github.com/Microsoft/TypeScript/issues/212 – 2017-06-07 07:30:08

回答

6

如果定义

type FAs = [Function, {}]; 

然后FAs类型的值将需要Function型的第一元件,{}型的第二元件,以及​​后续的元件。这就是TypeScript文字数组类型的工作原理。从TS docs

当访问组已知指标以外的元素,联合类型来代替:

这应该做你想要一切除了的事实,你会能够传递一个Function -type值作为数组的第三个元素等。但实际上无论如何都会是这种情况,因为Function{}兼容。

有没有办法解决这个问题。 TS中没有办法定义一个阵列类型,其中第一个元素是某些特定类型的元素,并且有任意数量的其他特定类型的其余元素。

我也怀疑类型系统是否支持可以说是任意长度的元组。

实际上,类型系统只有支持任意长度的元组。如果你说

type Tuple = [number, number]; 

这种类型是长约两或更大,包含数字与任何兼容阵列。如果你说

type Tuple = [string, number]; 

这种类型与任何阵列兼容,长度的两个或更长,具有字符串作为其第一元件,一个数字作为其第二,和一个字符串或数字作为它的第三等等。我不会说这种行为的原因是“基于计算机科学”。更重要的是TS要检查什么是可行的。

另一种方法

interface Arglist { 
    [index: number]: object; 
    0: Function; 
} 

const a1: Arglist = [func]; 
const a2: Arglist = [22];     // fails 
const a3: Arglist = [func, "foo"];   // fails 
const a4: Arglist = [func, obj]; 
const a5: Arglist = [func, obj, obj]; 
+0

我不知道尽管已经多次阅读文档页面,Typescript会为已知索引集外的元素使用联合类型。感谢您提供清晰的解释和文档链接。 – anticrisis

0

我很肯定这是Typecript 2.3中最好的。例如,你可以在lodash中看到类似这样的类型。

interface IMyCaller { 
    <R>([fn]: [() => R]): R; 
    <R,A>([fn, a]: [(a: A) => R, A]): R; 
    <R,A,B>([fn, a, b]: [(a: A, b: B) => R, A, B]): R; 
    <R,A,B,C>([fn, a, b, c]: [(a: A, b: B, c: C) => R, A, B, C]): R; 
    // keep adding these until you get tired 
} 

const myCaller: IMyCaller = ([fun, ...args]) => fun.apply(args); 
+0

这是我的想法,也有,但是打字稿的使用工会打字的元素没有特别定义是非常有帮助的。请参阅接受的答案以获得绝佳的描述以及一个重要的警告。 – anticrisis

+0

你说得对,如果你不需要严格的打字,这会很有帮助。我想我已经离开了,并没有对你的问题非常关注:) – dbandstra

相关问题