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