我在Typescript中使用Backbone.Marionette。我写了自己的Marionette类型描述。
var ProviderSpa = new Backbone.Marionette.Application();
ProviderSpa.addRegions({
'servicesRegion': "#services-offered"
});
ProviderSpa.servicesRegion.show();
我的问题是addRegions有一个副作用,即向ProviderSpa添加属性,TypeScript不知道,因此它抱怨“属性'servicesRegion'不存在于'Backbone.Marionette.Application'类型的值上
如何告诉TypeScript有关类型实例的动态属性添加?
答案 0 :(得分:3)
我在这个例子中使用了BackBone Marionette的缩减定义。
如果要将大量动态属性添加到对象中,您可能希望保留动态而不是尝试为它们创建声明或接口 - 尤其是将声明与新属性保持同步的开销对于实际动态属性进行静态类型的好处并不是我要付出的代价。
在此示例中,使用方括号语法访问属性意味着它传递类型检查而无需声明。重要的一点是在最后一行。
您可以在TypeScript playground上进行测试。
declare module Backbone {
export module Marionette {
export class Application {
addRegions(regions: any): void;
}
}
}
var servicesRegion = 'servicesRegion';
var ProviderSpa = new Backbone.Marionette.Application();
ProviderSpa.addRegions({
servicesRegion: "#services-offered"
});
ProviderSpa[servicesRegion].show();
答案 1 :(得分:2)
实际上,TypeScript和Marionette配合手套 这里的关键是根据类而不是动态属性进行思考。考虑到这一点,上面的代码就变成了这样:
class ProviderSpa extends Marionette.Application {
servicesRegion: Marionette.Region;
constructor(options?: any) {
super(options);
this.addRegions( { servicesRegion: "#services-offered" });
}
}
var providerSpa = new ProviderSpa();
providerSpa.show();
<强>更新强>
我刚刚在TypeScript: Using Backbone.Marionette and RESTful WebAPI.
答案 2 :(得分:0)
TypeScript类型系统无法考虑运行时效果,因为TypeScript类型仅在编译时存在。您必须在编译时适当地键入ProviderSpa。也许最简单的方法是为ProviderSpa创建一个具有addRegions和servicesRegion类型的接口,以便您可以这样做:
interface IProviderSpa { servicesRegion: ...; addRegions: ...; };
var ProviderSpa = <IProviderSpa> new Backbone.Marionette.Application();
如果Marionette有一个应用程序的接口类型,你甚至可以像下面这样扩展它:
interface IProviderSpa extends Backbone.Marionette.IApplication { ... }