How do I tell TypeScript about dynamic addition of properties? How do I tell TypeScript about dynamic addition of properties? typescript typescript

How do I tell TypeScript about dynamic addition of properties?


I have used a cut down definition of BackBone Marionette for this example.

If you have lots of dynamic properties being added to an object, you might want to leave things dynamic rather than attempting to create declarations or interfaces for them all - especially as the overhead of keeping declarations up-to-date with new properties vs the benefits of having static typing on what are actually dynamic properties isn't a cost I would pay.

In this example, accessing the property using square-bracket syntax means it passes the type checking without the need for a declaration. The important bit is on the last line.

You can test this on the 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();


Actually, TypeScript and Marionette fit hand in glove.
The key here is to think in terms of classes instead of dynamic properties. With that in mind, your code above becomes this:

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:
I've just posted part 1 of a blog article on TypeScript: Using Backbone.Marionette and RESTful WebAPI.


Runtime effects cannot be considered by the TypeScript type system as TypeScript types exist at compile time only. You will have to type ProviderSpa appropriately at compile time. Perhaps the easiest way to do it is make an interface for ProviderSpa that has addRegions and servicesRegion types so you can do:

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

If Marionette has an interface type for application, you could even extend that like the following:

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