为什么TypeScript有一个类型,然后有一个"相似类型"?例如Promise<T>PromiseLike<T>.

这两种类型之间有什么区别?我应该什么时候用?在这种情况下,为什么不只用一个Promise型呢?

推荐答案

如果你看一下定义文件(让我们看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的实现没有意见的库,那么与其这样做,不如:

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

我会这样做:

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

然后,即使我的库的用户正在使用不同的实现(bluebird),它也可以正常工作.

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

declare var Promise: PromiseConstructor;

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

interface PromiseConstructor {
    readonly prototype: Promise<any>;

    ...
}

I guess that the main reason that we have PromiseLike is that several implementations were available before the native one was supported (such as bluebird, Promises/A+, jQuery, and more).
In order for typescript to work with code bases that are using those implementations there must be a type other than Promise, otherwise there would be a lot of contradictions.

Typescript相关问答推荐

在控制器中使用@ DeliverGuards时实现循环依赖项时未定义的依赖项

输入具有相同键但值类型不同的对象

错误:note_modules/@types/note/globals.d.ts:72:13 -错误TS 2403:后续变量声明必须具有相同的类型

将对象属性路径描述为字符串数组的类型

如何根据参数的值缩小函数内的返回类型?

如何从具有给定键列表的对象类型的联合中构造类型

带有联合参数的静态大小数组

使Typescribe强制所有对象具有相同的 struct ,从两个选项

如何键入函数以只接受映射到其他一些特定类型的参数类型?

如何使我的函数专门针对联合标记?

被推断为原始类型的交集的扩充类型的交集

是否可以基于对象的S属性值[]约束对象的其他属性值用于类型化的对象数组?

如何使用Geojson模块和@Types/Geojson类型解析TypeScrip中的GeoJSON?

类型脚本-处理值或返回值的函数

17个Angular 的延迟观察.如何在模板中转义@符号?

扩展对象的此内容(&Q;)

如何在本地存储中声明该类型?

如何知道使用TypeScript时是否在临时工作流内运行

React Context TypeScript错误:属性';firstName';在类型';iCards|iSearch';

为什么过滤器不改变可能的类型?