The TypeScript team has just announced the release of TypeScript 2.1 which contains several long-awaited features (pun intended) for Dojo 2. Rather than repeating the excellent summary from the TypeScript team, we’ll look at how a few of these features will improve Dojo 2!
async/await
down-emitting for ES5
Dojo 2 supports exporting to ES5 environments. TypeScript 2.1 has added support for transpilation of async/await (a feature in the works for ES8) to environments prior to ES6. Async/await completes the transformation of making asynchronous code feel synchronous in the way we author it, as in the evolution from callbacks to Promise instances and generators. We expect to leverage async/await throughout the Dojo 2 codebase and will begin refactoring efforts to leverage this as soon as possible. This should reduce complexity and simplify the syntax of asynchronous operations throughout Dojo 2.
Static types of dynamically named properties
TypeScript 2.1 has added keyof, an index type query, which allows us to define static types for dynamically named properties. Given that it is common to expect parameterized property names, this helps express types that are common in JavaScript that were not previously easy to express with TypeScript.
Static types for dynamically named properties will make getters for properties on state in dojo/widgets type friendly.
Mapped and partial types
A partial type is one where we take an existing type, but all of its properties are optional. This is common for APIs which accept a property bag as a parameter. With Mapped types, we can simplify the syntax to express this, by iterating over the original type using keyof
, as a way to quickly create the new partial type. Mapped types are also useful for transforming types. For example, turning a group of synchronous properties into Promise instances.
TypeScript 2.1 has added Mapped types as well as Partial, Readonly, Record, and Pick constructs.
Partial types can be used to simplify state management in dojo/widgets. Essentially, widgets have a mandatory set of state needed to function correctly. Currently, that mandatory set of state cannot be enforced through typing due to partial state updates. With partial types, we will be able to express the minimum set of required state, while declaring that property of state can be updated.
ES8 object spread/rest
The spread and rest operators have been very useful on arrays and were introduced in ES6. ES8 has added these constructs to objects (currently a Stage 3 proposal) and TypeScript 2.1 has added object spread and rest.
When defining CSS classes, Maquette (the Virtual DOM library leveraged with Dojo 2) takes a classes
object with the class name as a key and the value as a boolean
(indicating whether or not the class is active). Before the object spread operator, these objects had to be manually composed ahead of time, merging multiple sources into one. Now, we’ll be able to succinctly compose classes
inline.
Better inference for literal types
Prior to TypeScript 2.1, String
, numeric
, and boolean
literal types were inferred only in the presence of an explicit type annotation. Now, literal types are always inferred for const
variables and readonly
properties, given that the type will not change. TypeScript 2.1 has improved inference for literal types.
Another improvement to TypeScript’s control flow analysis in 2.1 is literal type widening, which can now be controlled through explicit type annotations. If the expression of a literal type is inferred for a const
location without a type annotation, that const
is inferred with a widening literal type. When a const
location is an explicit literal type annotation, the const
variable is a non-widening literal type.
Dojo 2 is built with noImplicitAny
, forcing any types that cannot be inferred to be specified manually. Better type inference will dramatically reduce manual typing in several areas.
String and number literal narrowing on strict equality
TypeScript 2.1 has added non-null and non-undefined type guards. Previously, a property access or function call would create a compile-time error if the object or function was of a type that included null or undefined. With 2.1, type guards are extended to support non-null (==
or !=
) and non-undefined (===
or !==
) checks.
Configuration inheritance
Finally, a big feature we’ve been waiting for is configuration inheritance. Many projects may have different configurations for a subset of the project, whether it be different compilation targets or varying dependencies. Rather than having to include all configuration information redundantly, configurations can now easily inherit from another configuration, overriding where there is overlap in configuration settings.
This will allow us to remove duplicate configuration files in many modules, using a single base configuration that is managed in one place, extending as needed.
Conclusion
TypeScript continues to evolve to meet the needs of Dojo 2 and the development community as a whole. Early complaints about overly relying on the any
type or having limitations on what is possible are quickly being solved through the work of the TypeScript team!