【问题标题】:Implementing an interface with a call signature and method returning "this"使用调用签名和返回“this”的方法实现接口
【发布时间】:2019-08-17 22:35:09
【问题描述】:

前言:我们的团队正在开发一个基于 d3 构建的库。因为我们使用的是 TypeScript,所以我们也使用了来自 distinctlyTyped 的 d3 类型。尝试使用诸如 ScaleOrdinal 之类的接口以及那里的许多其他接口时会出现以下问题。


假设我们有一个包含调用签名和附加属性的接口:

export interface Foo<T> {
    // Let's pretend this will be the identity function
    (arg: T): T;

    // Let's pretend that this will be a no-op function
    // Note that this returns "this"    
    doFoo(): this;
}

我们如何才能以类型安全的方式正确地实现这样的接口[1]?经过研究,我发现了以下相关问题,所有这些问题都略有不同和/或相当古老。我想知道我们是否遗漏了什么,或者是否在此处向 TypeScript 团队提出问题:

  1. How to make a class implement a call signature in Typescript?
  2. TypeScript: Implement interface with both call signature and constructor signature
  3. TypeScript: Implement an interface with both call signature and indexing signature

请注意,接口对我们来说是外部的,因此实现它是我们唯一的选择。


¹为了这个问题,我希望实现明确地重述所有类型注释。

【问题讨论】:

    标签: typescript definitelytyped


    【解决方案1】:

    在 typescript 的最新版本(3.2 或 3.3 不确定哪个)中,当您声明一个函数时,您还可以为函数分配额外的属性,并且 typescript 会将这些视为这些属性的定义,而不是抱怨它们没有被定义:

    export interface Foo<T> {
        (arg: T): T;  
        doFoo(): this;
    }
    
    function foo(arg: number) : number {
        return arg
    }
    foo.doFoo = function <TThis extends typeof foo>(this: TThis): TThis { // no polymorphic this in simple functions
        return this
    }
    
    let o: Foo<number> = foo;  // foo is compatible with Foo<number>
    

    以前是这样做的,现在仍然有效的是使用Object.assign 来创建具有额外属性的函数:

    let o: Foo<number> = Object.assign(function (arg: number): number {
        return arg
    }, {
        doFoo: function <TThis>(this: TThis): TThis {
            return this
        }
    })
    

    【讨论】:

    • 谢谢!在签名中使用this: TThis 的技巧似乎是我们所缺少的。
    • @IngoBürk 还对其添加了一个约束以使 foo 成员可以访问
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-10
    相关资源
    最近更新 更多