Cool New Features Released in TypeScript 3.7
Tags: typescript, javascript, tutorial, webdev
Published: 2020-01-05 22:05:24

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

**Follow me on Twitter at https://twitter.com/AuMayeung**

**Many more articles at https://medium.com/@hohanga**

With the release of TypeScript 3.7, some great new features that are included from ES2020 that are now part of TypeScript. The new features include things like optional chaining, nullish coalescing, check for uncalled functions, and more.

In this article, we’ll look at some of them in more detail.

Optional Chaining
=================

Optional chaining is a feature that lets us get a deeply nested property of an object without worrying if any of the properties are `null` or `undefined`.

We can use the `?.` operator to get the properties of an object instead of using the usual dot operator. For example, instead of writing:

```typescript
let x = a.b.c.d;
```

We write:

```typescript
let x = a?.b?.c?.d;
```

With the optional chaining operator, we don’t have to worry about properties `b` or `c` being null or undefined, which saves us from writing lots of code to check is these properties exist.

If any of the intermediate properties are null or undefined, then undefined is returned instead of crashing the app with errors.

This means that we no longer have to write something like:

```typescript
let x = a && a.b && a.b.c && a.b.c.d;
```

To get the `d` property from the `a` object.

One thing to be careful is that if `strictNullChecks` flag is on, then we’ll get errors if we operate on an expression with the optional chaining operator inside a function with a parameter that has optional parameter as the operand.

For example, if we write:

```typescript
let a = { b: { c: { d: 100 } } };  
const divide = (a?: { b: { c: { d: 100 } } }) => {  
  return a?.b?.c?.d / 100;  
}
```

Then we get the error ‘Object is possibly ‘undefined’.(2532)’.

Nullish Coalescing
==================

The nullish coalescing operator lets us assign a default value to something when something is null or undefined.

An expression with the nullish coalescing looks like:

```typescript
let x = foo ?? bar;
```

Where the `??` is the nullish coalescing operator.

For example, we can use it as follows:

```typescript
let x = null;  
let y = x ?? 0;  
console.log(y); // 0
```

Then we get 0 as the value of `y`.

This is handy because the alternative was to use the `||` operator for assigning default values. Any falsy value on the left operand would cause the default value on the right operand to be assigned, which we might not always want.

The nullish coalescing operator only assigns the default value when the left operand is null or undefined.

For example:

```typescript
let x = 0;  
let y = x || 0.5;
```

In the code above, 0 is a valid value that can be assigned to `y`, but we still assign the default value of 0.5 to it because 0 is falsy, which we don’t want.

Assertion Functions
===================

TypeScript 3.7 comes with the `asserts` keyword which let us write our own functions to run some checks on our data and throws an error if the check fails.

For example, we can write the following to check if a parameter passed into our assertion function is a number:

```typescript
function assertIsNumber(x: any): asserts x is number {  
    if (typeof x === 'number') {  
        throw new Error('x is not a number');  
    }  
}  
assertIsNumber('1');  
assertIsNumber(1);
```

When we run the code above, we should get ‘Uncaught Error: x is not a number’.

In the code above, the `asserts` keyword checks whatever condition comes after it.

It’s a function that returns `void` which means that it doesn’t return anything. It can only throw errors if it doesn’t meet the condition we define.

Better Support for Functions that Return the Never Type
=======================================================

With TypeScript 3.7, now the TypeScript compiler recognizes functions that returns the `never` type is run in a function that returns some other type.

For example, before TypeScript 3.7, we have to write the following to avoid an error:

```typescript
const neverFn = (): never => {   
    throw new Error();  
};

const foo = (x: string | number): number => {  
    if (typeof x === 'string') {  
        return +x;  
    }  
    else if (typeof x === 'number') {  
        return x;  
    }  
    return neverFn();  
}
```

The code above would get us the error “Function lacks ending return statement and return type does not include ‘undefined’.” Because we did add `return` before the `neverFn()` function call.

TypeScript versions earlier than 3.7 don’t recognize the never function as a valid path because it doesn’t allow a path in the code that returns `undefined` if a return type is specified.

Now removing the `return` in `return neverFn();` will work if TypeScript 3.7 is used to compile the code.

Allowing Some Recursive Type Aliases
====================================

Type aliases that aren’t assigned to itself are now allowed with TypeScript 3.7. For example, the following is still not allowed:

```typescript
type Bar = Bar;
```

since it just replaces the `Bar` type with itself forever.

If we try to compile the code above, we would get the error “Type alias ‘Bar’ circularly references itself. (2456)“.

However, now we can write something like:

```typescript
interface Foo { };  
interface Baz { };  
type Bar = Foo | Baz | Bar[];
```

This is because the `Bar[]` type isn’t directly replacing `Bar` , so this type of recursion is allowed.

Generating Declaration Files when AllowJs Flag is On
====================================================

Before TypeScript 3.7, we can’t generate declaration files when the `--allowJs` flag is on, so TypeScript code that is compiled with JavaScript can’t have any declaration files generated.

This means that type checking can’t be done with JavaScript files that are being compiled, even if they have JSDoc declarations.

With this change, now type checking can be done with those JavaScript files.

Now we can write libraries with JSDoc annotated JavaScript and support TypeScript users with the same code.

The TypeScript compiler since 3.7 will infer the types of the JavaScript code from the JSDoc comments.

Uncalled Function Checks
========================

Forgetting to call a function by omitting the parentheses is a problem that sometimes causes bugs. For example, if we write the following:

```typescript
const foo = () => { };
const bar = () => {  
    if (foo) {  
        return true;  
    }  
}
```

We’ll get the error “This condition will always return true since the function is always defined. Did you mean to call it instead?(2774)” when we write the code above and try to compile it with the TypeScript 3.7 compiler.

This code wouldn’t give any errors before version 3.7.

Conclusion
==========

As we can see, TypeScript 3.7 gives us a lot of useful new features that aren’t available before. Optional chaining and nullish coaslecing operators are handy for avoiding null or undefined errors.

Recognizing function calls that return the `never` type is also handy for writing code with paths that don’t always return.

Having recursive type aliases help with combining some kinds of types into one alias.

For developers that write libraries, TypeScript 3.7 can infer types from JavaScript files that are compiled with the TypeScript compiler by checking the JSDoc comments.

Finally, uncalled functions are now checked by the TypeScript compiler if they’re written like we’re trying to access it as a property.