首页 文章

如何告诉TypeScript动态添加属性?

提问于
浏览
8

我在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关于类型实例的这些动态属性添加?

3 回答

  • 0

    我在这个例子中使用了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();
    
  • 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();
    

    Update:
    我刚刚发布了一篇关于TypeScript: Using Backbone.Marionette and RESTful WebAPI.的博客文章的第1部分

  • 3

    TypeScript类型系统无法考虑运行时效果,因为TypeScript类型仅在编译时存在 . 您必须在编译时适当地键入ProviderSpa . 也许最简单的方法是为ProviderSpa创建一个具有addRegions和servicesRegion类型的接口,以便您可以执行以下操作:

    interface IProviderSpa { servicesRegion: ...; addRegions: ...; };
    var ProviderSpa = <IProviderSpa> new Backbone.Marionette.Application();
    

    如果Marionette具有应用程序的接口类型,您甚至可以扩展它,如下所示:

    interface IProviderSpa extends Backbone.Marionette.IApplication { ... }
    

相关问题