2016-07-21 68 views
0

我有以下Javascript文件,我想导入到我的Angular 2项目中,而无需在Typescript中重新编写整个内容。Angular 2 - TypeError:无法读取未定义的属性'createMessage'

当一切都正确绑起来,我得到以下错误...

“EXCEPTION:类型错误:未定义无法读取属性‘的CreateMessage’”

这里是我的相应文件...

applicationAPI.js

var myApplication = myApplication || {}; 

(function(myApplication) { 

myApplication.Message = function() { 
    this.m_messageContents = "New Message"; 
}; 

myApplication.Message.prototype.getApplicationMessageContents = function() { 
    return this.m_messageContents; 
}; 

myApplication.SystemFactory = (function(){ 
    var factory =   
    { 
     createMessage: function() { 
      return new myApplication.Message(); 
     } 
    }; 
    return factory; 
}()); 

}(myApplication)); 

applicationAPI.d.ts

declare module "myApplicationAPI" { 

export interface Message { 
    getApplicationMessageContents(): string; 
} 

export class SystemFactory { 
    static createMessage(): Message; 
} 

} 

奇怪我可以得到这个工作时applicationAPI.js看起来像下面的相同applicationAPI.d.ts文件。

applicationAPI.js

(function() { 

this.Message = function() { 
    this.m_messageContents = "New Message"; 
}; 

this.Message.prototype.getApplicationMessageContents = function() { 
    return this.m_messageContents; 
}; 

this.SystemFactory = (function(){ 
    var factory =   
    { 
     createMessage: function() { 
      return new this.Message(); 
     } 
    }; 
    return factory; 
}());}()); 

上需要添加别的什么,这种情况下的工作有什么想法?这不是明摆着给我...

这是呼叫来自哪里...

home.component.ts

import { Component, OnInit } from '@angular/core'; 
import * as myApp from "myApplicationAPI"; 
@Component({ 
moduleId: module.id, 
selector: 'app-home', 
templateUrl: 'home.component.html', 
styleUrls: ['home.component.css'] 
}) 
export class HomeComponent implements OnInit { 
title: string; 

constructor() {} 
ngOnInit() { 
this.title = myApp.SystemFactory.createMessage().getApplicationMessageContents(); 
} 
} 
+0

你在哪一行得到错误?它看起来并不像你实际上在任何地方调用'SystemFactory.createMessage()' –

+0

这个调用来自我的“home.component.ts”文件,我添加了它。对于后面的用例,一切正常,但是一旦我在它打破的js中引入了“myApplication”对象。 – Daz

+0

我的直觉是问题出在.d.ts文件中,但我不确定解决方案。 – Daz

回答

0

你没有任何出口出来applicationAPI的。 JS,所以你不能从它进口任何东西。当你import * as myApp from "myApplicationAPI";你没有得到你认为你得到的。

你的第一本能可能是导出myApplication,但你应该导出类和接口,而不是实例。让Angular的依赖注入器处理实例。

我推荐的模式更像是这样的:

applicationAPI.ts

import Injectable from '@angular/core'; 
// either define Message in this file or import it as well 
// if you define it here, export it as well 

@Injectable 
export class Api { 
    static createMessage(): Message { 
    return new Message(); 
    } 
} 

home.component.ts

import Api from 'applicationAPI'; 
... 
    constructor (private api: Api) {...} 

并假设你的引导调用看起来像bootstrap(HomeComponent)它应改为

import Api from 'applicationAPI'; 
... 
bootstrap(HomeComponent, [Api]); 

这将确保每次注入Api时,它都是相同的实例,尽管如果类中的所有方法都是静态的,那么对您而言可能无关紧要。

.d.ts文件被typescript编译器用作参考,说的是“相信我,有些东西看起来像这样”,比如当你想让你的打字稿与一个JS库连接时。该库仍然必须在.d.ts文件之外的其他地方定义。 你放入.d.ts文件的任何内容都不会被浏览器执行,甚至被浏览器看到。如果Message仅在.d.ts文件中定义,那么您不能使用new Message,因为在JavaScript在浏览器中运行的那一天结束时,将不会有任何Message的定义。

+0

我理解这种方法,但是,我的目标是不重写任何应用程序API.js到应用程序API.ts中,而是从我的ts文件中使用它...是不是从我的“home.component .ts“来做到这一点?对我来说,看起来很奇怪,你不能仅仅将js文件添加为“reference \ import”并将代码添加到代码中。这里的问题是applicationAPI.js中“myApplication”的作用域丢失了,对吧?只是试图了解这个过程的真实行为,并没有从我能找到的很多高质量的例子。 – Daz

+0

您可能可以编写描述所有applicationAPI.js的行为和属性的.d.ts,然后在applicationAPI.js的底部添加一行:'window.myApp = myApplication;'。 .d.ts还需要声明该接口存在于Window对象上。那么你不需要导入任何东西来访问你的ts中的'window.myApp'。这就是jQuery如何与边打字一起使用(老实说,这和Angular没有关系)。 –

+0

将以下内容添加到我的d.ts文件中... 导出界面窗口{0} {0} {0} myApplication:any; } 在“home.component.ts”中产生以下构建错误: “Property'myApplication'在类型'Window'上不存在。”当我添加以下行... “if(typeof window.myApplication ===”undefined“){}” – Daz

相关问题