Ionic 3: New Features In TypeScript 2.1 & 2.2

Ionic 3.0 was released a couple weeks ago and it comes packed with a lot of new features, one of them is that it supports TypeScript 2.2.

In this post we'll have a look at some of the new features that have been introduced with TypeScript 2.1 and 2.2, so you'll be able to use them in your new Ionic 3 apps.

For a complete list of all TypeScript features, have a look here.

Untyped imports

A TypeScript 2.1 feature that is very much appreciated is the ability to import a third-party module that doesn't have a TypeScript Declaration File.

So an import like the one below would cause an error in older versions of TypeScript if there are no TypeScript Declarations installed for PouchDB.

import * as PouchDB from 'pouchdb';  

In the Ionic 2 starter templates there was a workaround introduced for this in the declarations.d.ts file, with the following line of code:

declare module '*';  

This line of code basically tells TypeScript that it shouldn't check if any module you're importing is actually available in your app. This can be very annoying if your code is prone to typos and your editor doesn't notify you straight away that there is an error there.

So now in Ionic 3 apps we don't need this workaround anymore and you should remove this line if it's still included in your app.

Object Spread and Rest

These are new features in TypeScript 2.1 and are implemented following the ES2017 specification for Object Spread/Rest and are similar to Array Spread/Rest in ES2015.

Spread

Spread creates a shallow copy of an object. We can easily add new properties to the copy or override copied properties with a new value.

let original = { a: 1, b: 2  };

// copy original
let copy1 = { ...original };

 // copy original and add c
let copy2 = { ...original, c: 3 };

// copy original and override x 
let copy3 = { ...original, a: 0 };  

// copy original and override with properties from another
let another = { b: 20, c: 30 };  
let copy4 = { ...original, ...another };  

Keep in mind that this is a shallow copy, so if the original object has properties that reference other objects, only the references will be copied.

Rest

You could already destructure an object in older versions of TypeScript but now you can use the rest syntax in destructuring as well.

let obj = { a: 1, b: 2, c: 3, d: 4 };  
let { a, b, ...remainder } = obj;

// a will be 1
// b will be 2
// remainder will be { c: 3, d: 4 } 

Async-Await

Async-Await was introduced in earlier versions of TypeScript, but could only be used with transpilation to ES2015 until TypeScript 2.1 which supports the use of it in applications that transpile to ES5.

Async-await uses Promises under the hood. It's only a different (easier to read) syntax for using Promises.

Let's say we are using the Ionic Platform service in our app to check when it's ready loading and we want to log to the console when that happens.

We'll create a wrapper method that calls platform.ready() which returns a Promise. Without async-await, it would look like this:

checkPlatformReady() {  
  return this.platform.ready()
    .then(readySource => {
      console.log('Platform ready:', readySource);
      return readySource;
    });
}

With async-await, the code will change to this, both implementations of checkPlatformReady will have a return type of Promise<string>:

async checkPlatformReady() {  
  let readySource = await this.platform.ready();
  console.log('Platform ready:', readySource);
  return readySource;
}

You can only use async-await with Promises, so if you want to use it with Observables, you'll have to call .toPromise() on the Observable.

Better checking for null/undefined

And lastly I wanted to mention this feature although it's not really usable in Ionic 3 apps at the moment because of an issue with Angular 4 that will hopefully be solved soon.

In TypeScript 2.2 the compiler will show you an error when you're trying to use nullable variables in the following situations (list taken from the release notes):

  • If either operand of a + operator is nullable, and neither operand is of type any or string.
  • If either operand of a -, , *, /, %, <<, >>, >>>, &, |, or ^ operator is nullable.
  • If either operand of a <, >, <=, >=, or in operator is nullable.
  • If the right operand of an instanceof operator is nullable.
  • If the operand of a +, -, ~, ++, or -- unary operator is nullable.

The compiler will only check this if you have strictNullChecks set to true in tsconfig.json.

So, for example, if we have a function that takes three parameters where the last one is optional and tries to multiply them, it will show an error during compilation.

function multiply(first: number, second: number, third?: number) {  
   return first * second * third;
}

// the line below will result in NaN because the third parameter is undefined, 
// but now you will get an error at compile time
multiply(1, 2);  

You can turn on strictNullChecks in your Ionic 3 app, but Angular 4 is not supporting it yet, so you'll see a bunch of errors during compilation. The ES5 code will still be generated, but it's not really a great developers experience.

Follow the status of this issue in Angular 4 here.

There are many more features in TypeScript 2.1 and 2.2, but I can't cover them all in this blog post. Here is a complete list all new features. If you don't feel confident in your TypeScript skills, sign up for my upcoming course below!