Typescript type checking - Backbone.Model instance

2019-07-02 19:37发布

I'm having a problem with Typescript and Backbone collections. Here's some groundwork:

class BaseChartModel extends Backbone.Model { }
class ScatterPlotModel extends BaseChartModel { }
class BarChartModel extends BaseChartModel { }

class MixedChartCollection extends Backbone.Collection { public model: BaseChartModel; ... }
class ScatterPlotCollection extends Backbone.Collection { public model: ScatterPlotModel; ... }
class BarChartCollection extends Backbone.Collection { public model: BarChartModel; ... }

Then I do the following:

 var scatterPlotCollection = new ScatterPlotCollection();
 var scatterPlotCollectionXhr = scatterPlotCollection.fetch({...});

 var barChartCollection = new BarChartCollection();
 var barChartCollectionXhr = barChartCollection.fetch({...});

 $.when(scatterPlotCollectionXhr, barChartCollectionXhr).done(() => {

       mixedCollection = new MixedChartCollection();
       mixedCollection.add(scatterPlotCollection.models, { silent: true });
       mixedCollection.add(barChartCollection.models, { silent: true });
       chartViewList = new MixedChartViewList({ collection: mixedCollection });

       chartViewList.render();

 });

Inside render():

public render(){
     var self = this;
     this.$el.html(this.template({}));

     this.collection.forEach(
    (chartModel: BaseChartModel) => {
            this.$el.append(self.AddChartView(chartModel).render());                  
    }
 );

     return this;
}

public AddChartView(baseChartModel: BaseChartModel) : BaseChartView {

      var newChartView: BaseChartView;

      if(baseChartModel instanceof ScatterPlotModel){
           newChartView = new ScatterPlotView({ model: baseChartModel});
      } else if (baseChartModel instanceof BarChartModel){
           newChartView = new BarChartView({ model: baseChartModel});
      } 
      ....       
}

Except instanceof never evaluates to true because it seems that the 'class type' deriving from Backbone.Model gets assigned to Backbone.Model.attributes rather than being an instance of the class itself. I believe this is because when implementing my classes that derive from Backbone.Model I followed this approach and it seems like it may be the reason for this problem. Basically it delegates get/set properties on the TS class to the underlying Backbone.model.get()/set() which in turn sets the values on the attributes property.

It seems I have to either drop this approach (and hope that was the problem) or figure out a way to do a loosely coupled type check similar to or using instanceof between the baseChartModel.attributes object and my class prototype for App.BackBone.Models.ScatterPlotModel

This breakpoint is at the line with instanceof comparison enter image description here

Any ideas?

2条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-07-02 20:26

I guess I know where a 'bug': somehow declaration

public model: CustomModelType

doesn't work;

But, if you will create a collection like this:

 new MyCustomCollection(null, { model: CustomModelType });

Then backbone will be able to create a models as expected.

Why it happens, I don't know :( May be a bug in type definition.

查看更多
\"骚年 ilove
3楼-- · 2019-07-02 20:39

The approach that you are using seems valid enough. I have plugged the following code into the TypeScript playground just to check a few javascript symantics:

class A { }

class B extends A { }

class Checker {
    static isA(input: A) {
        return (input instanceof A);
    }
}

var a = new A();
var b = new B();

document.writeln('a instanceof A ' + (a instanceof A) + '<br/>');
document.writeln('b instanceof B ' + (b instanceof B) + '<br/>');
document.writeln('b instanceof A ' + (b instanceof A) + '<br/>');
document.writeln('b instanceof A (via function) ' + Checker.isA(b) + '<br/>');

var aArray : A[] = [];

aArray.push(a);
aArray.push(b);

for(var i = 0; i < aArray.length; i++) {
    document.writeln('aArray[' + i + '] instance of A ' + (aArray[i] instanceof A) + '<br/>' );
}

This gives the following output:

a instanceof A true 
 b instanceof B true 
 b instanceof A true 
 b instanceof A checker true 
 aArray[0] instance of A true 
 aArray[1] instance of A true 

This must mean that the call

mixedCollection.add( scatterPlotCollection.models, { silent: true });

is causing the problem here.
Possibly scatterPlotCollection.models is NOT returning your original objects ( i.e. ScatterPlotModel or BarChartModel ), and is instead just returning [Object object], hence the instance of is failing ?

Hope this helps,

查看更多
登录 后发表回答