在 TypeScript 接口中覆盖/覆盖方法签名

Posted

技术标签:

【中文标题】在 TypeScript 接口中覆盖/覆盖方法签名【英文标题】:Overwrite/override method signature in TypeScript interface 【发布时间】:2017-02-16 19:48:53 【问题描述】:

在这个特定的示例中,我正在扩展 Array<T> 接口,如下所示:

interface BetterArray<T> extends Array<T> 
    push(this: BetterArray<T>, value: T): this;

参考注释 - Array&lt;T&gt;.push 是这样实现的

interface Array<T> 
    push(...items: T[]): number;

但我得到以下编译时错误:

接口“BetterArray”错误地扩展了接口“T[]”。 属性“推送”的类型不兼容。 类型 '(this: BetterArray, value: T) => this' 不可分配给类型 '(...items: T[]) => number'。 类型“this”不可分配给类型“number”。 类型“BetterArray”不可分配给类型“数字”。

有什么方法可以强制指示我想在我的界面上覆盖推送的 TypeScript(如 member hiding in C#)

注意 - 我使用的是 TypeScript 2.0

进一步阅读 - 看来这完全取决于返回类型 - 基本上我想通过接口强制执行,一个新的返回类型......

interface A 
    fn(): number;


interface B extends A 
    fn(): this;

接口“B”错误地扩展了接口“A”。财产类型 'fn' 不兼容。 类型 '() => this' 不能分配给类型 '() => number'。 类型“this”不可分配给类型“number”。 类型“B”不能分配给类型“数字”。

【问题讨论】:

【参考方案1】:

根据nitzan tomer's | answer

你只需要添加Array.push的原始签名:

interface BetterArray<T> extends Array<T> 
    push(...items: T[]): number;
    push(this: BetterArray<T>, value: T): this;

使用never 类型似乎可以解决这个问题。 Intellisense 接收到 never,“never” 返回,因此不会费心向您显示方法签名 (neat)

interface BetterArray<T> extends Array<T> 
    push(...items: T[]): never;
    push(this: BetterArray<T>, value: T): this;

【讨论】:

奇怪...但它似乎只删除了链中第一个 push(...) 之外的“never”方法 sig。 虽然使用 never 可以获得这种所需的智能感知效果,但这是对该功能的滥用,并且可能会在以后给您带来麻烦,因为它“谎报”实际实现。 @NitzanTomer 我不能将其解释为“此实现将'永远不会'发生”吗? -厚脸皮表情符号- 你可以。但是您正在覆盖返回数字的实际实现。这可能会在以后对您(或使用您的代码的其他人)产生影响。【参考方案2】:

您只需添加Array.push的原始签名:

interface BetterArray<T> extends Array<T> 
    push(...items: T[]): number;
    push(this: BetterArray<T>, value: T): this;

您想要做的问题是,如果thisBetterArray,那么您不能返回this,例如:

class BetterArrayClass<T> extends Array<T> 
    push(...items: T[]): number;
    push(this: BetterArrayClass<T>, value: T): this;
    push(this: BetterArrayClass<T>, ...items: T[]): number | this 
        return this;
    

错误:

类型 'BetterArrayClass' 不可分配给类型 'number |这个'。 类型“BetterArrayClass”不可分配给类型“this”。 这个:BetterArrayClass

原因可以从这个更简单的例子中看出:

class A 
    fn(this: A, num: number): this 
        return this; // Error: Type 'A' is not assignable to type 'this'. this: A
    


class B extends A 
    fn(num: number): this 
        if (num < 0) 
            return super.fn(num);
        
        return this;
    

如果在B.fn 中我们调用super.fn,那么this 不是A 而是B,无论如何我们都希望返回B 的实例。 这不是A.fn 所描述的。

【讨论】:

非常感谢,但是当涉及到甚至不使用类并且必须更深入地研究 JS 时,它有点复杂,因为 TypeScript 根本无法发出构建我正在构建。关于这一点,我找到了另一个解决方案,基于你的。查看我的解决方案 我想知道你的这个 typescript 无法处理的构造是什么 好吧,它需要一个可以执行此操作的构造函数: new (n?: T): T & Q ...当我尝试这样做时,TypeScript 会像婴儿一样哭泣上课! 您能否再次编辑您的问题并更好地解释您要做什么?似乎您想覆盖 Array.push 方法并返回数组实例而不是通常返回的数字。如果是这种情况,那么你是对所有数组都这样做(覆盖原型)还是构造这个扩展数组的新实例?如果是的话怎么办?

以上是关于在 TypeScript 接口中覆盖/覆盖方法签名的主要内容,如果未能解决你的问题,请参考以下文章

如何覆盖外部 TypeScript 接口

java的重写重载覆盖的差别

用 Jest 测试 Typescript 接口

用相同的方法在一个类中实现两个接口。哪个接口方法被覆盖?

Python 覆盖子类中方法返回的类型提示,无需重新定义方法签名

TypeScript:覆盖和修复包的类型定义