【问题标题】:Force custom JavaScript to respect TypeScript interfaces强制自定义 JavaScript 尊重 TypeScript 接口
【发布时间】:2017-01-14 12:19:03
【问题描述】:

给定以下接口:

interface Person {
    constructor: Function;
    getFullName(): string;
}

interface PersonConstructor {
    new (firstName: string, lastName: string): Person;
    prototype: Person;
    createPerson(firstName: string, lastName: string): Person;
}

我想使用 JS 而不是 TS 自定义编写一个类,如下所示:

var Person = (() => {
    function Person(firstName: string, lastName: string) {
        var _firstName = firstName;
        var _lastName = lastName;

        this.getFullName = () => _firstName + " " + _lastName;
    }

    Person.createPerson = (firstName: string, lastName: string): Person => new Person(firstName, lastName);

    return Person;
})();

但我收到以下错误:

类型 '(firstName: string, lastName: string) => void'

我还希望能够将我的自定义 JS 用作 TypeScript 中的基类...

class FamousPerson extends Person {

}

但我收到此错误...

Type '(firstName: string, lastName: string) => void' 不是 构造函数类型。

如何让我的自定义 JS 尊重我的界面?

注意:接口遵循 TS 1.4 中采用的相同构造函数(静态接口)模式

【问题讨论】:

    标签: typescript


    【解决方案1】:

    你可以让它工作,但要使用any

    interface Person {
        getFullName(): string;
    }
    
    interface PersonConstructor {
        new (firstName: string, lastName: string): Person;
        prototype: Person;
        createPerson(firstName: string, lastName: string): Person;
    }
    
    var Person = (function(): PersonConstructor {
        function Person(firstName: string, lastName: string) {
            var _firstName = firstName;
            var _lastName = lastName;
    
            this.getFullName = () => _firstName + " " + _lastName;
        }
    
        (Person as any).createPerson = (firstName: string, lastName: string): Person => new Person(firstName, lastName);
    
        return Person as any;
    })();
    

    (code in playground)

    您的代码的更改:

    1. Person 接口中删除了constructor
    2. 实际的构造函数闭包被声明为返回一个PersonConstructor
    3. 在添加createPerson 函数并返回它时将Person 转换为any

    虽然这适用于您的第一个请求,但如果您打算覆盖 Person 类方法,您会遇到第二个请求。
    例如:

    class User extends Person {
        constructor(firstName: string, lastName: string) {
            super(firstName, lastName);
    
            console.log(this.getFullName());
        }
    
        getFullName(): string {
            return "user: " + super.getFullName();
        }
    }
    

    创建一个新的User 将记录:"first last" 而不是"user: first last",这是因为User.getFullName 是在原型上定义的,但随后在Person 的ctor 中被新定义覆盖。
    在编译好的js代码中看的更清楚:

    var Person = (function () {
        function Person(firstName, lastName) {
            var _firstName = firstName;
            var _lastName = lastName;
            this.getFullName = function () { return _firstName + " " + _lastName; };
        }
        Person.createPerson = function (firstName, lastName) { return new Person(firstName, lastName); };
        return Person;
    })();
    var User = (function (_super) {
        __extends(User, _super);
        function User(firstName, lastName) {
            _super.call(this, firstName, lastName);
            console.log(this.getFullName());
        }
        User.prototype.getFullName = function () {
            return "user: " + _super.prototype.getFullName.call(this);
        };
        return User;
    }(Person));
    

    (code in playground)

    能够覆盖方法的唯一方法(不会遇到很多麻烦)是在原型上而不是在实例上实现它们。
    但这将剥夺使用您使用 var 定义的“私人成员”的能力,我认为这是您想要开始这样做的原因。

    【讨论】:

    • 正是如此。我真正想要的只是一种在 TypeScript 中使用每个实例函数和真正的“私有”变量来定义基于闭包的实现的方法,而不是所有东西都绑定到原型。我讨厌安德斯和他的团队将他们的意识形态强加给我的事实!
    • “绑定到原型”是使 OO 成为可能的原因,否则您将陷入痛苦的世界。我强烈建议你放弃这种方法,因为它会导致你工作比需要的更努力,所以一些变量将是真正“私有的”。
    • 根据我的经验,这从来都不是问题。我用很少的努力就实现了 OO、继承和私有成员,所以除非我大量忽略了某些东西,否则恐怕这是一个有争议的问题
    • 如何覆盖示例中的getFullName 方法?
    • ……那个老栗子。这很容易,直到您需要进行超级调用,您只需要在子类型中重新定义 getFullName,但是在使用闭包时,您不能调用超级类型的实现(至少据我所知)
    【解决方案2】:
    1. Person.createPerson 替换为`Person['createPerson']

    2. 您不能在 JS 中扩展自定义编写的类。 TypeScript 无法理解 var Person 是一个类。你有什么理由不能在 TS 中编写类吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-01
      • 2018-02-04
      • 2012-09-25
      • 1970-01-01
      • 2015-07-27
      • 2018-01-10
      相关资源
      最近更新 更多