【问题标题】:Implementing fluent generic class methods Typescript实现流畅的泛型类方法 Typescript
【发布时间】:2019-12-17 02:51:09
【问题描述】:

如何在集合类上实现流畅的(可链接的)通用映射函数?考虑以下内容:

class Array_<T> {
    private _arr: T[]

    constructor(iterable: Iterable<T>) { this._arr = [...iterable] }

    [Symbol.iterator]() { return this._arr[Symbol.iterator]() }

    map<Y>(projector: (item: T) => Y): Array_<Y> {
        return new Array_((function* (iterable: Iterable<T>) {
            for (const element of iterable) {
                yield projector(element)
            }
        })(this))
    }
}

class ArrayCustom<T> extends Array<T> { }

let mappedArr = new ArrayCustom([1,2,3]).map(element=>element.toString())

mappedArr 的推断类型是Array_&lt;string&gt;,但我希望它是ArrayCustom&lt;string&gt;

【问题讨论】:

  • 使用名称Array 是不幸的,因为通常在范围内已经有一个名称为Array 的数组构造函数。而在 TypeScript 中,Array&lt;T&gt; 类型已经与 T[] 相同。这充其量是令人困惑的(如果您在自己的模块或命名空间中隐藏名称),最坏的情况是错误(如果您尝试在全局范围内执行此操作)。考虑改变它。
  • @jcalz 这仅用于说明目的;我的代码中没有使用名称Array
  • 除非您试图说明阴影或名称冲突,否则我建议您在问题代码中更改它...请注意下面的答案必须如何将其更改为其他内容 (AppArray)为了正确编译答案。

标签: typescript class generics methods fluent


【解决方案1】:

你可以做的是在ArrayCustom中重新定义map

class ArrayCustom<T> extends AppArray<T> {
  map<Y>(projector: (item: T) => Y): ArrayCustom<Y> {
    return super.map(projector)
  }
}

// let mappedArr: ArrayCustom<string>
let mappedArr = new ArrayCustom([1, 2, 3]).map(element => element.toString());

PS:我将您的 Array 更改为 AppArray - Array 出现重复类型编译错误,因为它已经作为全局类型存在。

您不能使用Polymorphic this types,因为您每次都在map 中为流畅的界面返回一个新对象。那将要求对象相同。此外,无法对返回的数组类型进行参数化,因为 TypeScript 不支持 higher kinded generic types(请参阅 jcalz 的评论)。

旁注: 如果您想对数组进行浅层克隆,映射所有项目并且不依赖异步生成器,您可以使用 Array.from 更轻松地实现 map

map2<Y>(projector: (item: T) => Y): AppArray<Y> {
  return new AppArray(Array.from(this, projector));
}

Playground

【讨论】:

  • 这个答案看起来不错......只是为了添加更多细节,如果没有一些手动步骤(如覆盖子类方法)就无法完成此操作,因为 TypeScript 没有 higher kinded generic types 类型参数本身可以采用类型参数。所以没有办法拥有像A extends MyArray 这样的泛型然后使用A&lt;T&gt;
  • @jcalz 谢谢你,非常有用!如果您不介意,我会将该链接添加到答案中。
猜你喜欢
  • 2020-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-19
  • 1970-01-01
  • 2022-01-19
  • 2020-09-10
相关资源
最近更新 更多