首页 > 解决方案 > 如何在 TypeScript 中扩展 IterableIterator

问题描述

我正在尝试Iterable使用类似于 C# 的 where 方法进行扩展Enumerable.where()。扩展Array原型很容易,但是我正在努力寻找如何扩展Iterable.

这是声明:

declare interface Iterable<T> {
    where<T>(this: Iterable<T>, predicate: (item: T) => boolean): Generator<T>;
}

问题在于实施。扩展方法编译得很好,但是在运行时尝试在 an Array(它是 an Iterable)或 any上使用该方法时Iterable,它会抛出where()未定义的。Array您只需将方法实现添加到,Array.prototypeIterable没有原型:

function* where<T>(this: Iterable<T>, predicate: (item: T) => boolean): Generator<T> {
    for (const item of this) {
        if (predicate(item)) {
            yield item;
        }
    }
}

Iterable.prototype = function* where(...)不起作用,因为Iterable没有原型。

这是所需的用法:

public myMethod(myIterable: Iterable<number> ) {
    console.log(myIterable.where(i => i > 3));
}

我该如何延长Iterable?我应该延长IterableIterator吗?

有人设法做到了另一个线程(https://stackoverflow.com/questions/62008192/typescript-`extending`-iterableiterator-for-array-type-but-return-a-simple-type)但他没有展示他如何扩展 Iterable 并告诉我问另一个问题。

标签: javascripttypescript

解决方案


您可以扩展,IteratorPrototype在这种情况下,您的方法将使用内置的迭代器array.keys()或星号函数,但不适用于数组之类的迭代器。

正如您所说的那样,没有办法扩展Iterable,因为在运行时不存在这样的东西。一般来说,更常见的做法是设计自己的“monad”,而不是扩展内置原型:

result = Enumerable(someIterable)
    .where(...)
    .map(...)
    .etc(...)
    .toList()

推荐阅读