Javascript TypeScript中匿名/内联接口的实现

Javascript TypeScript中匿名/内联接口的实现,javascript,interface,typescript,typescript1.6,Javascript,Interface,Typescript,Typescript1.6,我刚刚开始使用TypeScript,我试图理解为什么以下内联对象定义被认为是无效的。我有一个对象集合——它们的类型与我无关,但它们实现了接口,因此当我遍历它们时,我知道接口方法将出现在集合中的每个对象中 当我试图创建一个包含实现所需方法所需的私有信息的对象时,遇到了一个“编译器”错误: interface Doable { do(); } function doThatThing (doableThing: Doable) { doableThing.do(); } doTh

我刚刚开始使用TypeScript,我试图理解为什么以下内联对象定义被认为是无效的。我有一个对象集合——它们的类型与我无关,但它们实现了接口,因此当我遍历它们时,我知道接口方法将出现在集合中的每个对象中

当我试图创建一个包含实现所需方法所需的私有信息的对象时,遇到了一个“编译器”错误:

interface Doable {
    do();
}

function doThatThing (doableThing: Doable) {
    doableThing.do();
}

doThatThing({
    private message: 'ahoy-hoy!', // compiler error here
    do: () => {
        alert(this.message);
    }
});
编译器错误消息是
类型的“{message:string,do:()=>void;}”
参数不可分配给类型Doable。对象文字必须指定已知属性,并且类型Doable中不存在“message”。请注意,如果我在函数调用之外定义对象,则会给出相同的消息,即

var thing: Doable;
thing = {
    private message: 'ahoy-hoy!', // error here
    do: () => {
        alert(this.message);
    }
};
doThatThing(thing);
如果我还添加了“意外”方法,则会出现相同的错误:

doThatThing({
    do: () => {
        alert("ahoy hoy");
    },
    doSecretly: () => { // compiler error here now
        alert("hi there");
    }
});
我查看了JavaScript,发现内联对象定义中的
这个
被限定为全局对象:

var _this = this; // wait, no, why!?
function doThatThing(doableThing) {
    doableThing.do();
}
doThatThing({
    message: 'ahoy-hoy!',
    do: function () {
        alert(_this.message); // uses global 
    }
});
我试图在TypeScript中搜索有关接口内联实现的信息,但找不到任何与此问题相关的信息

我可以确认“固定”编译的JS按预期工作:

function doThatThing(doableThing) {
    doableThing.do();
}

doThatThing({
    message: 'ahoy-hoy!',
    do: function () {
        alert(this.message);
    }
});
…这对我来说是有意义的,因为(据我所知)这是隐式调用对象构造函数,所以
应该限定在新对象实例的范围内

看起来唯一的解决方案是将每个实现声明为一个实现接口的类,但这感觉真的是倒退/繁重,因为每个类只有一个实例。如果被调用函数的唯一约定是实现接口,那么为什么对象不能包含其他成员

抱歉,结果比我预期的时间长……总之,我在问:

  • 为什么在TypeScript中内联接口实现(“匿名类”)被认为是无效的?具体来说,编译器错误意味着什么,它能防止什么
  • 为什么要在“编译”JavaScript中生成对全局对象的范围重新分配
  • 假设这是我的错误(例如,编译器错误是防止某些不希望出现的情况所必需的),那么,唯一的解决方案真的是像这样提前显式声明一个类吗
    好的,我终于发现了问题2的问题-我在这里使用胖箭头
    =>
    来声明对象的方法:

    doThatThing(<Doable>{ 
        private message: 'ahoy-hoy!', 
        do: () => { // using fat arrow: global scope replaces new object's scope
            alert(this.message);
        }
    });
    
    doThatThing({
    私人信息:“喂,喂!”,
    do:()=>{//使用胖箭头:全局范围替换新对象的范围
    警报(此消息);
    }
    });
    
    …将全局范围“吸入”到方法中。使用较长的语法修复了该问题,如下所示:

    doThatThing(<Doable>{
        private message: 'ahoy-hoy!',
        do: function() { // using "regular" anonymous function syntax, "this" meaning is preserved
            alert(this.message);
        }
    });
    
    doThatThing({
    私人信息:“喂,喂!”,
    do:function(){//使用“常规”匿名函数语法,“此”含义将被保留
    警报(此消息);
    }
    });
    
    总而言之:

  • 未答复
  • 我的代码中有一个输入错误,我应该使用“function()”而不是“=>”;以及
  • 使用接口断言对象的类型将删除编译器错误

  • 作为未来读者的旁注:也可以在不使用
    函数
    关键字的情况下定义内联函数:
    {message:'ahoy hoy!',do(){alert(this.message);}}
    。此语法只是普通函数的简写,不会像箭头函数那样绑定词法
    This
    。应该使用
    do=()=>{…}
    -赋值确保它使用
    Doable
    实例范围,即使从事件处理程序等调用。
    var _this = this; // very wrong, and now hidden
    function doThatThing(doableThing) {
        doableThing.do();
    }
    doThatThing({
        message: 'ahoy-hoy!',
        do: function () {
            alert(_this.message); // s/b "this.message", which works in JS (try it)
        }
    });
    
    doThatThing(<Doable>{ 
        private message: 'ahoy-hoy!', 
        do: () => { // using fat arrow: global scope replaces new object's scope
            alert(this.message);
        }
    });
    
    doThatThing(<Doable>{
        private message: 'ahoy-hoy!',
        do: function() { // using "regular" anonymous function syntax, "this" meaning is preserved
            alert(this.message);
        }
    });