The administration abundance chain, accepted for rolex replica uk its affordable accouterment and home apparatus offerings, is now peddling high-end artist accoutrement from above labels including, Chanel, uk replica watches and Zac Posen.The artist appurtenances will be awash on The Sears Marketplace through third-party vendors. The fake watches move may assume counterintuitive, but a Sears agent says it takes the administration abundance aback to its roots, which already included affairs cars.
Failing Forward – Page 3

TypeScript and Dojo

Over the years, I have used many different frameworks and libraries that have tried to make JavaScript more consitent and and powerful. From VanillaJS, to jQuery, to AnglarJS, I took many of them out for a spin. One of the first frameworks that I used, however, was a little one known as dojo.

There are three things that you  learn about dojo:

  • it is very powerful
  • it can be tricky to learn
  • it doesn’t play well with others

This last point means that dojo apps are typically written the ‘dojo’ way. That is to say that the modules are created using dojo’s version of AMD, interfaces are created using its UI framework, unit tests are created using its testing framework, and “classes” are created using its class system. The amazing thing about that statement is that dojo comes will all of these capabilities right out of the box. Unfortunately, this high level of integration and functionality does not integrate into the workflow of a lot of the technologies in the larger JavaScript ecosystem.

One technology that I have been seriously considering recently is TypeScript. Both of these technologies are designed to make large client-side applications easier to build and maintain: dojo brings a large amount of infrastructure support for building multi-layer browser applications and TypeScript brings strong type support that help prevent typos, refactor-induced bugs, etc.

In order to bring these two technologies, two things needed to be done:

  1. Type definitions had to be generated for the dojo API
  2. A method had to be developed to get the dojo and TypeScript module system to work together

Generating type definitions for dojo

This post will discuss the strategy that I used to created the type definitions that would provide the basic type-support that makes TypeScript so compelling. A type definition is a file (or files) that describes the interfaces and usages of some JavaScript code in a way that TypeScript can use to enforce typing rules. A collection of type definitions has be put together at DefinitelyTyped where they can be accessed by anyone that is trying to integrate existing JavaScript libraries into a TypeScript application.

Process

The creation of the type definitions was done in four phases. First, the dojo API was used to get the basic information. Next, the data was transformed into a collection of JavaScript objects that described the entities, their abilities, and how they linked to each other. Then the resulting objects was used to generate the final type defintion files. Finally, the generated definitions were hand polished in order to smooth over areas where the API documentation was incorrect or generated structures that are not legal TypeScript (e.g. a function in a base class being overridden to be a property in the child class).

Extracting the API

The dojo community has done a phenominal job creating extensive documentation. Like many other frameworks, the API for dojo is automatically generated from the source code leading to a consistent structure to the API’s HTML.

In order to extract this data, a simple JavaScript was written that would retrieve each API page-fragment, add it on the local page, and then examine it using standard DOM querying techniques.

At the base of this structure is a file called tree.json that looks like this:

tree.json

This file is used by the page to generate a tree control that is used to navigate the API. Conveniently, this file also describes dojo’s parent-child relationships and serves as the basic structure for the extraction.

The next step in the extraction process is to get the detailed information for each API entry. For a class, this would include the description, constructor arguments, properties, and methods; functions would have the description as well as the parameters and return values. To accomplish this, we need to get the same page fragments that the API site uses into our own page for examination. Due to cross-site scripting issues, this can’t be done directly. Instead the calls had to go up the the generator’s server which would retrieve the information from the dojo site and the return the result to the client. Along the way, it caches the data so that the application didn’t have to make the requests throughout the development process (there are almost 2500 entities that make up the dojo API, so network perfomance was pretty important).

When each item was loaded, then its “type” (as described by the entry in tree.json) would be used to determine what kind of document fragment would be expected. This allowed Function objects (e.g. dojo/request) to be extracted as a function while classes (e.g. dijit/form/Button) would be extracted as a class. As an example, consider dojo/request. It is a function that is used to make requests via XMLHttpRequest or other transport. The API page looks like this:

dojo_request

As you can see, the page shows the description, parameters (with type and description) and the return type of the function. You also see that dojo overloads the request function as an object too. The request function has a property “del” that is a shortcut for a delete request (there are also shortcuts for get, post, and put…). This gives us all of the information that we need to generate the API entry.

Processing the API

After the API entries have been read, they are sent to the server to have the type definitions generated. At this point, the data is very good (due to the high quality of the documentation), but there are occasional issues, such as misspelled types, that the server will begin to address. The server executes its work using the following steps:

  • Merge entries that refer to the same path
  • Cleanse the data
  • Generate the type definition for the entry

Merge entries

Dojo is very good at relating similar concepts together. Consider dojo/request again. Its basic usage is as a function. This function takes a url and collection of parameters to request information from a server. Dojo/request also has object traits (mentioned above) that enabled simpler accessor methods that automatically setup the request to use a specific HTTP verb (GET, POST, PUT, and DELETE). Both the function semantics and the object semantics are contained on the API page. However, dojo/request is also a “package” that contains a collection of specific request types (XMLHttpRequest, IFrame, and Node to name a few). This multi-layered nature is perfectly acceptable JavaScript, but it generates two entities in TypeScript that can have duplicate entries. As a result, the server will review all of the entries that get sent to it. If it finds to entries with the same path, it will merge the entries into a single object for type definition generation.

Cleanse the data

As I have said before, the dojo documentation is very good, but any framework as large as this is bound so have some challenges maintaining consistency with the API. That, combined with TypeScript’s selection of primitives (e.g. all numbers are type number. No distinction exists for integers and floats) leads to a need to map and correct the API types to be valid TypeScript types.

Generate the type defintions

Originally, I set out to generate a single type definition file. However, this file ended up being something north of 500K lines of code. This caused Visual Studio (the IDE I was using) great consternation as it tried to process the massive file. In the end, the type definitions are written out as multiple script files consisting of dojo, dijit, doh, and each dojox sub-module in its own file. The generation of the files were pretty straightforward since the previous steps have already done the heavy-lifting.

Hand polishing

The last step of the type definition generation process was to review the generated files and eliminate any remaining errors. These errors could come from a wide variety of soures, but mostly spawned from missing entries in the dojo API meaning that generated interfaces weren’t being honored. There were also occasions where a base class would define something to be a property, but a child class would override it with a function. This is perfectly valid JavaScript, but it made TypeScript sad.

Result

Overall, the process of generating the type definitions took about two weeks and a half weeks. The generator application (found here) took about two weeks with 2 or 3 days of polishing. After some back and forth the the DefinitelyTyped crew (the type definitions overwhelmed their CI process), the pull request got accepted and is ready to be used (here). I expect that the next several months will see changes being made where the generator missed some assumptions, but I believe that this process layed a strong foundation for integrating dojo and TypeScript together and allowing ever larger JavaScript applications to be built without sacrificing maintainability.