如何在 TypeScript 中为特定类型的泛型类型创建扩展方法

How to create an extension method for a specific type of generic type in TypeScript

对于我正在从事的半教育性副项目,我有一个 TypeScript interface,它在实现它的任何对象上公开一个 id 变量。在此应用中,Array<>IIdable 对象是很常见的。

由于此应用程序不使用数据库,我正在尝试做的是为跟踪这些 IIdable 列表的服务实现自动增量器。自然地,我考虑过如下 "JavaScript" 方式添加扩展...

Array<MyProject.Models.IIdable>.prototype.getNextId = () => {
    let biggestId: number = 0;
    for (let current of this) {
        if (current.id > biggestId)
            biggestId = current.id;
    }

    return biggestId + 1;
};

...但是 Visual Studio 代码会抛出一些错误,其中之一是:

Cannot find name 'prototype'

我觉得这有问题,因为 Array<T> 是一个 JavaScript 'primitive',并且所有东西都是 JavaScript 中的 object(因此TypeScript 的创建是为了完全减少或避免一些问题。)但是,我意识到我对 JavaScript 和 TypeScript 的了解已经足够 "dangerous",这意味着我知道的事情足以让自己去做一些很愚蠢的东西。

如果我使用的是 C#(TypeScript 不是),我会编写这样的扩展方法:

public static GetNextId(this List<IIdable> source)
{
    // ...Read each IIdable's ID to figure out the next biggest to give.
}

...不幸的是,据我所知,我不能完全做到这一点。在发布这个问题之前,我做了一些关于在 TypeScript 中编写扩展方法的研究。一个这样的答案是用新方法修改主机类型的接口,在这种情况下我不想这样做。我只想为我们处理 Array<IIdable> 而不是其他情况的情况添加扩展。

因此,我必须问:我可以用什么方法在 TypeScript 中为特定类型的事物在泛型类型上编写扩展方法?

泛型class Array只有一个原型;访问原型时不能指定类型参数。但是,您可以覆盖方法上的 this 类型。下面是您将如何声明然后定义方法。请注意,您必须使用 function 函数,它能够接收 this 参数,而不是箭头函数,箭头函数始终使用定义范围内的 this (在本例中是全局对象)。

interface Array<T> { 
  getNextId(this: MyProject.Models.IIdable[]): number;
}

// The `this` type for the function is taken from the declaration above.
Array.prototype.getNextId = function() {
    let biggestId: number = 0;
    for (let current of this) {
        if (current.id > biggestId)
            biggestId = current.id;
    }

    return biggestId + 1;
};