2017-05-01 34 views
13

为什么打字稿有一个类型,然后是“类型”?这方面的一个例子是Promise<T>PromiseLike<T>。这两种类型有什么区别?我应该什么时候使用它们?在这种情况下,为什么不只有一个Promise类型?为什么打字稿使用“Like”类型?

+0

如果我问你有关阵列和ArrayLike对象以及它们有何不同,你会怎么回答? – Thomas

+1

你看过[lib中的定义](https://github.com/Microsoft/TypeScript/blob/master/lib/lib.es6.d.ts#L1323)吗? –

+0

感谢您的链接。很高兴看到定义的类型,但是这个问题更侧重于两种类型之间的语义差异,而不仅仅是它们的接口。这两种类型定义的目的是什么?为什么作者选择这样做?我认为@Thomas暗示这里有正交的API设计内涵。他们是什么?覆盖这些更大设计问题的答案就是我所追求的。如果你喜欢,我可以更新问题的措辞。 – Stewart

回答

16

如果你看看定义文件(让我们拿lib.es6.d.ts),那么它非常简单。

例如,ArrayLike接口:

interface ArrayLike<T> { 
    readonly length: number; 
    readonly [n: number]: T; 
} 

不止有限Array一个:

interface Array<T> { 
    length: number; 
    toString(): string; 
    toLocaleString(): string; 
    push(...items: T[]): number; 
    pop(): T | undefined; 
    concat(...items: T[][]): T[]; 
    concat(...items: (T | T[])[]): T[]; 
    join(separator?: string): string; 
    reverse(): T[]; 
    shift(): T | undefined; 
    slice(start?: number, end?: number): T[]; 
    sort(compareFn?: (a: T, b: T) => number): this; 
    splice(start: number, deleteCount?: number): T[]; 
    splice(start: number, deleteCount: number, ...items: T[]): T[]; 
    unshift(...items: T[]): number; 
    indexOf(searchElement: T, fromIndex?: number): number; 
    lastIndexOf(searchElement: T, fromIndex?: number): number; 

    // lots of other methods such as every, forEach, map, etc 

    [n: number]: T; 
} 

这是件好事,两地分居的,因为我可能希望有这样的功能:

function getSize(arr: Array<any>): number { 
    return arr.length; 
} 

console.log(getSize([1, 2, 3])); // works 

但它不会与这个:

function fn() { 
    console.log(getSize(arguments)); // error 
} 

它的结果与此错误:

Argument of type 'IArguments' is not assignable to parameter of type 'any[]'.
Property 'push' is missing in type 'IArguments'.

但如果我这样做既会工作:

function getSize(arr: ArrayLike<any>): number { 
    return arr.length; 
} 

(更多ArrayLike in MDN

同样有PromisePromiseLike,如果我正在建立一个不关心工具的图书馆的Promise的entation则不用这样做:

function doSomething(promise: Promise<any>) { ... } 

我会做到这一点:

function doSomething(promise: PromiseLike<any>) { ... } 

那么即使我的媒体库的用户使用的是不同的实现(蓝鸟)都可以正常运行精细。

如果你会注意到的Promise的定义是这样的:

declare var Promise: PromiseConstructor; 

这使得它非常具体的,其他实现可能有不同的属性,例如不同的原型:

interface PromiseConstructor { 
    readonly prototype: Promise<any>; 

    ... 
} 

我猜测我们有PromiseLike的主要原因是有几个实现在原生支持之前可用(如bluebird,Promises/A+,jQuery,等等)。
为了使打字稿与使用这些实现的代码库一起工作,必须有除Promise以外的其他类型,否则会有很多矛盾。

+0

很好的答案,但在这种特殊情况下,我仍然感到困惑。为什么在'PromiseLike'中有'catch()'有问题? – rekire

+0

@rekire我不知道他们为什么选择在'PromiseLike'中只包含'then',但我的猜测是某些promise实现没有'catch'(例如它看起来像[Promises/A +](https: //promisesaplus.com/)不)。 –