【问题标题】:Typescript: `this` types and generic functions打字稿:`this` 类型和泛型函数
【发布时间】:2017-01-23 16:51:27
【问题描述】:

假设我想创建一个接口addable,它使用__add__ 方法描述类,该方法将一个类的对象添加到同一类的另一个对象。

假设我想要一个独立的函数add,它接受同一个类的两个addable 对象并返回它们的总和。

我的第一个想法是在界面中使用this 类型:

interface addable<T> {
    __add__: (this: T, other: T) => T;
}

然后我实现我的类如下:

class Point implements addable {
    constructor(public x: number, public y: number) { }
    __add__(other: Point) {
        return new Point(this.x + other.x, this.y + other.y);
    }
}

失败:

类“Point”错误地实现了接口“addable”。

属性“add”的类型不兼容。类型 '(other: Point) => Point' 不可分配给类型 '(other: this) => this'。

类型“Point”不可分配给类型“this”。

编辑:经过一些研究,我发现this 类型指的是this 对象,而不是this 对象的类。所以这次尝试注定要失败。

the example 1

我的第二个想法是使用带有this 伪参数的泛型:

interface addable<T> {
    __add__: (this: T, other: T) => T;
}

上面指定的类定义在这种情况下有效。但是,当我尝试定义独立的 add:

const add = <T>(a1: addable<T>, a2: addable<T>) => a1.__add__(a2);

我明白了:

'addable' 类型的 'this' 上下文不可分配给方法的 'T' 类型的'this'。

the example 2

有人知道如何实现所需的行为吗?

EDIT2:

界面

interface Addable<T> {
    add: (this: Addable<T>, other: Addable<T>) => Addable<T>;
}

显然是我想要的。独立功能将是

const add = <T>(a1: Addable<T>, a2: Addable<T>) => a1.add(a2)

但是这个定义太宽松了。它实际上对Addable 的任意两个实例进行类型检查,而不仅仅是对同一类的实例进行类型检查

interface Addable<T> {
    add: (this: Addable<T>, other: Addable<T>) => Addable<T>;
}
class Point implements Addable<Point> {
    constructor(public x: number, public y: number) { }
    add(other: Point) {
        return new Point(this.x + other.x, this.y + other.y);
    }
}
class Num implements Addable<Num> {
    constructor(public number: number) { }
    add(other: Num) {
        return new Num(this.number + other.number);
    }
}
const add = <T>(a1: Addable<T>, a2: Addable<T>) => a1.add(a2)

var p1 = new Point(1, 1);
var num1 = new Num(10);

const wrongAdded = p1.add(num1);  // correctly fails

const wrongAdded2 = add(p1, num1);  // typechecks! why???

推断的添加类型是&lt;{}&gt;。这听起来不对,但我对打字稿的熟悉程度不足以要求任何见解。

【问题讨论】:

    标签: typescript polymorphism


    【解决方案1】:

    这是否达到了您想要的效果...我已经完全删除了参数this。如果需要,我会重命名它。这允许将一个点添加到另一个点,返回结果点...

    interface Addable<T> {
        add: (other: T) => T;
    }
    
    class Point implements Addable<Point> {
        constructor(public x: number, public y: number) { }
    
        add(other: Point) {
            return new Point(this.x + other.x, this.y + other.y);
        }
    }
    
    var p1 = new Point(1, 1);
    var p2 = new Point(3, 3);
    
    var added = p1.add(p2);
    
    alert(added.x + ' ' + added.y);
    

    注意:我在这里调整了名称,以使它们与野外的 TypeScript 更加一致 - 因为我不希望其他程序员将您的约定复制/粘贴到生产中。如果您愿意,您可以随意使用名称 addable__add__ :)

    【讨论】:

    • 感谢您的回答。那么你将如何实现独立方法 add(a1, a2) 呢?
    • 我想通了!接口必须是interface Addable&lt;T&gt; { add: (this: Addable&lt;T&gt;, other: Addable&lt;T&gt;) =&gt; Addable&lt;T&gt;; } 和函数const add = &lt;T&gt;(a1: Addable&lt;T&gt;, a2: Addable&lt;T&gt;) =&gt; a1.add(a2)。我想要这个参数的原因是你只能添加同一个类的两个对象,而不是任意两个 Addable 对象。
    • 过早的快乐 :) 该解决方案允许您 add 任意两个 Addables,而不仅仅是同一类。
    【解决方案2】:

    问题的最后一个版本几乎就在那里。我对泛型类型的约束使用了错误的语法。最终版本是这样的

    interface Addable<T> {
        add: (this: Addable<T>, other: Addable<T>) => Addable<T>;
    }
    class Point implements Addable<Point> {
        constructor(public x: number, public y: number) { }
        add(other: Point) {
            return new Point(this.x + other.x, this.y + other.y);
        }
    }
    
    class Num implements Addable<Num> {
        constructor(public number: number) { }
        add(other: Num) {
            return new Num(this.number + other.number);
        }
    }
    const add: <T extends Addable<T>>(a1: T, a2: T) => T = function (a1, a2) {
        return a1.add(a2);
    }
    
    var p1 = new Point(1, 1);
    var p2 = new Point(2, 2);
    var num1 = new Num(10);
    
    const added = p1.add(p2);
    const added2 = add(p1, p2);
    
    const wrongAdded = p1.add(num1);  // Fails
    
    const wrongAdded2 = add(p1, num1);  // Fails
    

    【讨论】:

      猜你喜欢
      • 2023-02-22
      • 2020-07-08
      • 2021-11-26
      • 2020-01-23
      • 2017-09-15
      • 2018-05-02
      • 2020-03-22
      • 1970-01-01
      • 2022-11-11
      相关资源
      最近更新 更多