如何在 Typescript 4.0.3 中正确扩展数组原型?

Eug*_*leo 2 arrays prototype interface typescript

我正在尝试Array使用一些自定义方法扩展基本接口。我环顾了 SO 和 typescript 文档,最后将以下代码放在一起:

// In module Func.ts

declare global {
  type Array<T> = {
    intersperse(mkT: (ix: number) => T): T[];
  };
}

if (!('intersperse' in Array.prototype)) {
  Array.prototype.intersperse = function intersperse<T>(this: T[], mkT: (ix: number) => T): T[] {
    return this.reduce((acc: T[], d, ix) => [...acc, mkT(ix), d], []).slice(1);
  };
}
Run Code Online (Sandbox Code Playgroud)

但是,我收到以下错误:

// On type Array<T> = { ... }
Duplicate identifier 'Array'.ts(2300)

// On Array.prototype.intersperse = ...
Property 'intersperse' does not exist on type 'any[]'.ts(2339)
Run Code Online (Sandbox Code Playgroud)

此外,每当我尝试intersperse在其他文件中使用时,我都会收到错误消息

Property 'intersperse' does not exist on type 'Element[]'.ts(2339)
Run Code Online (Sandbox Code Playgroud)

这是可以预料的,考虑到声明Func.ts似乎没有用。由此,我认为 SO 问题已经过时(或不完整),并且此后发生了一些变化。

那么,消除这些错误并扩展 Array 原型的最佳扩展方法是什么?在你说我不应该这样做之前——是的,我知道所有的风险,无论如何我做了一个明智的决定。

Tit*_*mir 6

Array被定义为接口而不是类型。打字稿中的接口是开放式的,可以通过多个声明添加。类型不共享相同的功能。

export{}
declare global {
  interface Array<T>  {
    intersperse(mkT: (ix: number) => T): T[];
  }
}

if (!Array.prototype.intersperse) {
  Array.prototype.intersperse = function intersperse<T>(this: T[], mkT: (ix: number) => T): T[] {
    return this.reduce((acc: T[], d, ix) => [...acc, mkT(ix), d], []).slice(1);
  };
}
Run Code Online (Sandbox Code Playgroud)

游乐场链接

正如 TJ Crowder 提到的,您可能会考虑使用Object.defineProperty以确保该属性不可枚举:

export {}
declare global {
  interface Array<T>  {
    intersperse(mkT: (ix: number) => T): T[];
  }
}

if (!Array.prototype.intersperse) {
  Object.defineProperty(Array.prototype, 'intersperse', {
    enumerable: false, 
    writable: false, 
    configurable: false, 
    value: function intersperse<T>(this: T[], mkT: (ix: number) => T): T[] {
      return this.reduce((acc: T[], d, ix) => [...acc, mkT(ix), d], []).slice(1);
    }
  });
}

Run Code Online (Sandbox Code Playgroud)

游乐场链接

  • @TJCrowder “in” 的问题是打字稿问题。`in` 充当 `Array.prototype` 的类型保护,并且由于 `intersperse` 被声明为始终存在于 `Array.prototype` 上,因此类型保护 `!('intersperse' in Array.prototype)` 将使 ` `never` 类型的 Array.prototype` (因为 TS 认为就声明的类型而言,这种条件永远不会成立)。`undefined` 测试不会充当 `Array.prototype` 的类型保护,仅充当 `Array.prototype.intersperse` 的类型保护,并且由于我们只是分配它,所以编译器认为 `Array.prototype 什么类型并不重要.intersperse` 是 (2认同)