orad
orad

Reputation: 16074

Converting Backbone structures to TypeScript

Looking at Backbonejs' implementation of the extend function, it shows that it isn't a basic prototype extension, and when backbone extensions are converted straight to TypeScript classes some things stop functioning. What is the right way to convert each component of Backbonejs (Model, Collection, Route, View, History) to a typescript class and make sure nothing is broken?

Thanks!

Update: The answer in this Q/A can also work for other backbone constructs.

Upvotes: 3

Views: 1223

Answers (2)

jon_wu
jon_wu

Reputation: 1152

Updated solution for Backbone 1.4+

In 2019 (Backbone 1.4.0), a preinitialize method as added for all Backbone objects, including for the Router. The PR has more background.

This is helpful for ES6 classes and TypeScript.

Here's an example from the docs:

class Router extends Backbone.Router {
  preinitialize() {
    // Override execute method
    this.execute = function(callback, args, name) {
      if (!loggedIn) {
        goToLogin();
        return false;
      }
      args.push(parseQueryString(args.pop()));
      if (callback) callback.apply(this, args);
    }
  }
}

You can also define these as getters, but the above strategy has less friction with the current @types/backbone, which don't have types for some paths like getters, even though they technically still work with ES6.

Upvotes: 0

Diullei
Diullei

Reputation: 12434

This is because the code generated by TypeScript first calls the Router constructor and then declares the routes.

Code generated by TypeScript compiler

...
function AppRouter() {
    _super.apply(this, arguments);

    this.routes = { // <= routes defined after _super constructor
        "*actions": "defaultRoute"
    };
}
...

To fix this just call the Backbone Router function _bindRoutes() on your TypeScript object constructor.

Example:

class AppRouter extends Backbone.Router {
    routes = {
        "*actions": "defaultRoute"
    }

    constructor(){
        super();
        // call _bindRoutes() here function to bind your routes
        (<any>this)._bindRoutes();
    }

    defaultRoute() {
        document.write("Default Route Invoked");
    }
}

var app_router = new AppRouter();

Backbone.history.start();

Download a sample code here

Upvotes: 1

Related Questions