我无法解释为什么我收到错误但代码有效。是编译器错误吗? (我使用带有Angular 2的Visual Studio代码)
class A
{
fun(a: number)
{
return a+2;
}
}
A.prototype.F = function() { return "F here!"+this.fun(1); } // This makes error: The property 'F' does not exist on value of type 'A'
var a: A = new A();
console.log(a.F());
奖金:这根本不起作用! (无法访问this.fun())
A.prototype.F2 = () => { return "F2 here!"+this.fun(1); } // ()=>{} is not working! cause _this is not defined!
...
console.log(a.F2());
编辑#1
正如@seangwright所说,我需要使用Module Augmentation,但......
就我的A
课程使用简单示例而言,我无法使用Angular的ComponentFixture。如果我像在Typescript示例中那样执行此操作,这应该可以解决我的问题:
declare module '@angular/core/testing' // I was trying without this line and with 'global' instead of '@angular/core/testing' but nothing helps
{
interface ComponentFixture<T>
{
TestOf(cssSelector: string): string;
}
}
但我仍然收到错误:
&#39; ComponentFixture&#39;仅指类型,但用作值 这里&#39;
此时:
ComponentFixture.prototype.TextOf = function(cssSelector: string): string
{
...
}
还有更多错误,例如当我尝试使用它时:
let fixture: ComponentFixture<EditableValueComponent>;
fixture = TestBed.createComponent(EditableValueComponent);
我得到了:
&#39; ComponentFixture&#39;不能分配给类型 &#39; ComponentFixture&#39 ;.两种不同的类型 这个名字存在,但它们是无关的。物业&#39; TestOf&#39;是 类型&#39; ComponentFixture&#39;
中缺少
再次:代码有效,但有很多编译错误。或者也许我错过了一些明显的东西?
答案 0 :(得分:0)
根据您格式化代码的方式,我感觉您是C#开发人员。
在Typescript中声明你的类之后,类型系统希望它具有你定义的属性(形状)。
您想要使用的类型系统越多,您的对象的动态就越少。
那就是说,你的代码正确运行(转换)的原因是因为这是在Typescript的结构类型系统的上下文中的错误,而不是Javascript的动态类型系统。所以,Typescript会告诉你A
在编译时没有属性F
,但Javascript并不关心它是否在运行时添加。
一个解决方案是merge the class with an interface
class A {
fun(a: number) {
return a + 2;
}
}
interface A {
F(): string;
}
A.prototype.F = function () { return "F here!" + this.fun(1); }
var a: A = new A();
console.log(a.F());
另一种方法是暂时放弃类型系统
class A {
fun(a: number) {
return a + 2;
}
}
(A.prototype as any).F = function () { return "F here!" + this.fun(1); }
var a: A = new A();
console.log((a as any).F());
但是这会变得冗长,容易出错并失去类型系统带来的好处。
你提到你正在使用带有Angular 2的Typescript。如果你想要一个更动态的语法,你可以在ES2015中编写。但是,您将失去Angular 2使用Typescript获得的一些好处(更好的工具,更小的部署)。
你的第二个例子根本不起作用的原因与使用JJ中的Scope (or execution context),与ES2015 arrow functions无关,与strict mode无关。
箭头函数不会创建自己的这个上下文,所以它在封闭的上下文中有其原始含义。
与第一个示例不同,您没有使用传统的function
声明语法,而是使用() => {}
箭头函数语法。用你的第一个例子
A.prototype.F = function() { return "F here!"+this.fun(1); }
this
指的是将要执行的任何上下文F()
。由于您在A
的原型上定义它,它将在{{1}的上下文中执行}}。 A
有A
方法,因此.fun()
将与您上课中定义的方法相同。
使用第二个示例,this.fun()
不会在F2
的上下文中执行,尽管被定义为其原型的方法。相反,箭头函数语法允许A
在F2
的上下文中运行,enclosing context
是全局window
对象,除非您在Typescript Playground中运行,在这种情况下< / p>
在浏览器中,它不再可能通过严格模式函数引用窗口对象。
因此this
将为undefined
,而fun()
上的undefined
调用将会产生错误。
尝试在console.log(this)
功能中添加F2
。
A.prototype.F2 = () => { console.log(this); return "F2 here!"+this.fun(1); }
当您运行已编译的Javascript时,您可能会看到Window
已登出到控制台,然后可能出现Uncaught TypeError: _this.fun is not a function
使用https://bl.ocks.org/anonymous/raw/bf1921449e33d89ba6259167231f5b32/编写一些Typescript,看看工具告诉你的内容,创建的Javascript是什么,然后运行它以查看你的Javascript是否正确。