8

我在打字稿中使用 Backbone.Marionette。我已经写了我自己的木偶类型描述。

var ProviderSpa = new Backbone.Marionette.Application();
ProviderSpa.addRegions({
    'servicesRegion': "#services-offered"
});
ProviderSpa.servicesRegion.show();

我的问题是 addRegions 具有向 ProviderSpa 添加属性的副作用,TypeScript 不知道,因此它抱怨“Backbone.Marionette.Application”类型的值上不存在“属性“servicesRegion”。

我如何告诉 TypeScript 这些动态属性添加到一个类型的实例?

4

3 回答 3

3

在这个例子中,我使用了 BackBone Marionette 的简化定义。

如果你有很多动态属性被添加到一个对象中,你可能希望让事情保持动态,而不是尝试为它们创建声明或接口——尤其是保持声明与新属性保持同步的开销与好处对实际上是动态属性的内容进行静态类型不是我愿意付出的代价。

在此示例中,使用方括号语法访问属性意味着它无需声明即可通过类型检查。重要的一点在最后一行。

您可以在TypeScript 游乐场上进行测试。

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();
于 2012-10-26T08:24:25.217 回答
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 的博客文章的第 1 部分:使用 Backbone.Marionette 和 RESTful WebAPI。

于 2014-02-28T05:24:12.680 回答
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 { ... }
于 2012-10-25T19:19:58.760 回答