Adding TypeScript Type Definitions to the Stream JavaScript API Client Library

Dwight G.
Dwight G.
Published September 5, 2017 Updated November 8, 2019

TypeScript is a language that Stream has been interested in for quite some time. Over the past year, we've had an increasing number conversations with TypeScript and Angular developers. So naturally, it's been our ambition to eventually distribute Type Definitions for our JavaScript API Client library. That time has come. The process of coding Type Definitions is straight forward. However while developing Type Definitions, it's useful to see them in action in a real project, so uncertainty about how the .d.ts file would eventually be distributed proved to be a sticking point when writing and testing Type Definitions for the first time. Of the options available, which are detailed below, we chose to bundle Type Definitions within our JavaScript package. This post brings together what we learned and the steps we went through to get there. This should help other developers new to TypeScript and Type Definitions to do likewise.

A TypeScript primer

Let's begin with a quick primer on the language and highlight why Type Definitions are of interest. TypeScript is a modern programming language that is a superset of the JavaScript language. It is compiled (in fact, is transpiled) to plain JavaScript. This is quite similar to the CoffeeScript language and also to aspects of the Babel project which transpiles between JavaScript versions. The main features of TypeScript:

  • It is an Object Oriented Programming language
  • It provides for optional type hints (which we'll focus on in this post)
  • It offers the possibility of codebase integration between TypeScript and JavaScript

If you're looking for more, check this concise summary of the benefits of TypeScript by our friends at Ionic. Type Definitions are the concept behind some of the most desirable benefits of TypeScript. They define the "shape" and types associated with a library's API. They enable developers to add type hints to their code base and these are checked at compilation time which helps avoid bugs. They also facilitate advanced IDE features like "code completion" which can improve the developer experience and speed up development.

Options for distributing Type Definitions

Before we go too far, it's important to note that there are a few ways that developers can create and distribute the Type Declaration File (identifiable by the .d.ts extension). npm.js is the de facto tool and repository for JavaScript packages so it's a logical place for our Type Definitions to end up. The choice of how to get Type Definitions into npm depends on the project's primary language (TypeScript or JavaScript) as well as one's ability to commit/contribute changes, and ultimately publish new versions to npm.

Developers and contributors of TypeScript projects

It should be no surprise that for projects written in TypeScript, it is exceptionally easy to generate Type Definitions. It is simply a matter of including the --declaration and/or related tsc TypeScript compiler options. From there the generated Type Definitions can be inspected and refined manually to ensure they match the developer's intent. From there it is simply a matter of including the generated .d.ts file in the resulting JavaScript package and publishing it to npm.

Developers and contributors of JavaScript projects

Developers and contributors working on JavaScript packages have more work to do. As stated in the TypeScript project documentation on publishing Declarations Files, the .d.ts file should be bundled directly within the JavaScript project (emphasis added):

There are two main ways you can publish your declaration files to npm:

  1. bundling with your npm package, or
  2. publishing to the @types organization on npm.

If you control the npm package you are publishing declarations for, then the first approach is favored.

This bundling is convenient because the source and Type Definition is available in one place and are versioned together as part of one package.

Everyone without the ability to commit or raise PRs and publish package versions

The final option that's available to everyone is to use the DefinitelyTyped repository and the @types organization. This is an independent, community managed collection of Type Definitions. When it is impractical to bundle Type Definitions with a JavaScript package, DefinitelyTypes is the alternative recommended by the TypeScript project. The main downside to this approach is a side-effect of physically separating code that is otherwise closely related. It leaves the potential for version mismatches and also introduces lead-time associated with submitting Pull Requests through the DefinitelyTyped project repository. Still, it's considerably better than no Type Definitions at all.

Coding the Type Definitions

The Declaration Files section of the TypeScript documentation provides guidance to both TypeScript and JavaScript developers. There's not too much more to be said. In addition to the documentation, there are two related open source projects that offer additional support:

  • dtslint: a utility built on TSLint for linting TypeScript declaration (.d.ts) files [dtslint on Github]
  • dts-gen: creates starter TypeScript definition files for any module or library [dts-gen on Github]

As we chose to add Type Definitions directly to our JavaScript package, we end up with four additional files in our JavaScript package:

  • .tsconfig
  • tslint.json
  • tests-getstream.ts
  • getstream.d.ts

In addition, the project's package.json now declares the "types" property. This allows the TypeScript compiler and IDEs with TypeScript support to locate the Type Declaration file and apply the Type Definitions it contains.

The end result

With the Type Definitions bundled with the JavaScript API Client library, the benefits that come from type hints, static type checking and IDE code completion are immediately available.

Code completion is shown in Sublime with the TypeScript plugin.[/caption] To start using Stream's newly minted JavaScript API Client library with Type Definitions, simply install or upgrade to v3.6.0. To see it in action in a demo project, take a look at the Stream Angular Example project on Github.