关于javascript:TypeScript Array.prototype.map声明

TypeScript Array.prototype.map declaration

规格

根据Array.prototype.map()的MDN规范,应像这样使用映射...

1
var new_array = arr.map(callback[, thisArg])

问题

TypeScript有几个map的重载声明,这使得extend Array< T >很难。

我希望看到这个(在lib.d.ts中)...

1
map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];

但是lib.d.ts也有这些...

1
2
3
4
5
6
7
map<U>(this: [T, T, T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U, U, U];

map<U>(this: [T, T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U, U];

map<U>(this: [T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U];

map<U>(this: [T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U];

异议

由于JavaScript不允许方法重载,并且TypeScript也不允许用于类实现,因此我也不认为TypeScript也不允许环境声明。

问题

  • 为什么TypeScript允许对环境声明重载签名?
  • 如何在扩展Array的类中覆盖地图实现?
  • 我也在GitHub上提出了这个...
    https://github.com/Microsoft/TypeScript/issues/13785

    注意

    ReadonlyArray< T >仅具有一个用于地图的签名,即...

    1
     map<U>(callbackfn: (value: T, index: number, array: ReadonlyArray< T >) => U, thisArg?: any): U[];


    (1)如果不允许在环境声明中重载签名,您将如何在本机js函数/方法中获得不同的签名?
    lib.d.ts中有很多重载,反映了本机js对象的工作方式。

    (2)您需要告诉编译器您正在涵盖所有可能的声明签名。
    在您的情况下,您可以执行以下操作:

    1
    2
    3
    4
    5
    6
    class A< T > extends Array< T > {
        map<U>(this: Array<U>, ...args: any[]);
        map<U>(this: Array< T >, callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[] {
            return [];
        }
    }

    第一个重载签名将照顾那些您不想打扰的签名。


    您的问题涉及TypeScript的不同方面。我将单独处理它们,然后将它们放在一起。

    数组< T >

    接口在TypeScript中起到双重作用:

  • 它们允许您为其他(尚不存在)的类创建" true"接口以实现。当您实现它时,您必须完整地实现它,因为该接口提供了其所有成员可用的保证。
  • 它们使您可以定义已经存在的javascript类型的接口。当您想使用众多现有库之一并且仍然具有静态类型化的优点时,这非常有用。这些接口通常在.d.ts文件中定义(并且lib.d.ts文件包含基本的JavaScript类型)。这些接口是针对现有类型量身定制的,通常不适合您实现。虽然可以,但是可以实现其所有成员。
  • Array< T >接口是第二种,因此并不意味着您可以实现。

    函数中的this参数

    在可以传递参数的意义上,函数定义中的this:参数不是真实参数。它允许您指定函数主体中this值的期望类型。如果未指定,this的类型将为any,这通常不是很有用。

    函数/方法重载

    在TypeScript中,函数和方法在Java或C#之类的语言中不会被重载。您不能多次实现它,但是可以定义备用签名,以允许静态类型返回类型或使用变量参数的函数。尤其是在.d.ts定义文件中,这是有用的并且经常是必需的,因为现有的库使用JavaScript的弱类型来返回值或期望不同类型的参数。那使你的反对是错误的。您需要函数重载来容纳这些JavaScript构造。

    元组

    在JavaScript数组中,您可以在其每个插槽中分配多种类型的值。在TypeScript数组定义中,您指定一种由编译器强制执行的类型。为了填补空白,您可以定义元组。像[number, string, string]这样的类型会转换为JavaScript数组any[],并且TypeScript仍然可以强制执行静态类型。

    摘要

    如果数组是实际的[T, T][T, T, T][T, T, T, T][T, T, T, T, T],则在Array< T >中针对对象的数组方法重载会引入一个静态类型的this参数。这并不意味着该数组提供了多个map方法。这是相同的方法,但是对于某些特定的数组类型来说,它是重载的。它在lib.d.ts中提供,因此并非由您设计实现。您可以扩展基础类(即使没有接口也已存在),但是重载不会对您造成伤害(至少在这种情况下不会对您造成伤害,因为它们仅提供this参数)。