为什么 TypeScript 使用“Like"?类型? [英] Why does TypeScript use "Like" types?

查看:62
本文介绍了为什么 TypeScript 使用“Like"?类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么 TypeScript 有一个类型,然后是一个like 类型"?一个例子是 PromisePromiseLike.

Why does TypeScript have a type and then a "like type"? An example of this is Promise<T> and PromiseLike<T>.

这两种类型有什么区别?我应该什么时候使用它们?在这种情况下,为什么不只有一种 Promise 类型?

What are the differences between these two types? When should I use them? In this case why not just have one Promise type?

推荐答案

如果你查看定义文件(让我们以 lib.es6.d.ts) 然后就很简单了.

If you look at the definition files (let's take lib.es6.d.ts) then it's pretty straight forward.

例如 ArrayLike界面:

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

数组

is more limited than the Array one:

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;
}

将两者分开是件好事,因为我可能想要这样的功能:

It's good to have the two separated because I might want to have a function like this:

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

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

但它不能用于此:

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

结果是这个错误:

IArguments"类型的参数不可分配给类型的参数'任何[]'.
IArguments"类型中缺少push"属性.

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

但如果我这样做,两者都会起作用:

But both will work if I do this:

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

(更多关于 MDN 中的ArrayLike)

PromisePromiseLike 相同,如果我正在构建一个对Promise 的实现没有意见的库,那么而不是这样做:

The same with Promise and PromiseLike, if I'm building a library which isn't opinionated about the implementation of the Promise then instead of doing this:

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

我会这样做:

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

那么即使我的库的用户使用不同的实现(bluebird),它也能正常工作.

Then even if the user of my library is using a different implementation (bluebird) it will work just fine.

如果你注意到的定义承诺是这样的:

If you'll notice the definition of Promise is this:

declare var Promise: PromiseConstructor;

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

Which makes it very specific, other implementations might have different properties, for example a different prototype:

interface PromiseConstructor {
    readonly prototype: Promise<any>;

    ...
}

我想我们拥有 PromiseLike 的主要原因是在支持原生实现之前有几种实现可用(例如 bluebirdPromises/A+jQuery 等).
为了使打字稿与使用这些实现的代码库一起工作,必须有一个类型而不是 Promise,否则会出现很多矛盾.

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 使用“Like"?类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆