More TypeScript Types You Need To Know … Better

You probably know at least some of these types already, but you might be surprised at some of the nuance of using them

Having static types in JavaScript is enormously valuable, but knowing how to use them appropriately can also be difficult. I think you might be surprised by some of the details of these types.

Null and Undefined Types Are More Than You Think

In JavaScript running typeof on null returns ‘object’. Some devs might have thought its type is null, since undefined’s type is undefined. Now to make things more confusing however, in TypeScript null’s type is null. Don’t believe me? Here’s a sample.

console.log(typeof null);
console.log(typeof undefined);
let val1: null = null;console.log(val1);
let val2: undefined = undefined;console.log(val2);

If you run this code you get this

So this detail is definitely something to be aware of when using these types. Here’s another question did you know that by default you can assign null and undefined to any object type? If this is not your experience it would be because your tsconfig.json file uses either strict: true or strictNullChecks: true. If you are using strict, which you should, then this behavior is not allowed without using a union. Here’s an example in non-strict and strict mode.

// non-strict this works
let val: number = undefined;// strict this works
let val: number | undefined = undefined;

Also note even if you have strict turned on null and undefined can still be set to an any variable, which does make sense. But is also another good reason not to use the any type.

Never Type

If you read my previous article on this topic, you’ve seen the any alternative called unknown. The never type is also a lesser known type. This type is a bit strange in that it attempts to describe the scenario where nothing is returned from a function, not even void. Huh? So then when can one return “never”. Here are some examples

function error(): never {     
    throw Error("failed!");
function neverFinish(): never {     
    while(true) {}

So now you’re like well that’s utterly useless. Actually not at all. Let’s give another example that’s a little more realistic.

function processSomeString(msg: string): string | never {    
    if(msg) {        
        // do some string work here        
        return "I finished processing your string.";    
    throw Error("no message given error!");

If you run this code you will get an exception of course, but here’s the thing as TypeScript developers we know the value of static typing. It’s more than just having compiler help. It’s also about explicitness and communication. When we annotate with types we’re not just telling the compiler what we intend, but we’re also letting other devs know what we’re up to.

Therefore having something like never is an explicit way of giving other developers, not just the compiler, notice that something unusual could occur. To me I’ve always felt that functions that could throw an exception should indicate that in their signature. And using never is an easy clean way of doing that. In Swift programming you can indicate that a function can throw an exception in the function signature like this.

func canThrowErrors() throws -> String

I think both languages allowing for explicitness in communicating the possibility of unexpected situations is a very useful feature.

That’s it. Happy coding.

Here’s part one of this series.

As always if you like helping other devs try this

Published by David Choi

Developer Lead Where devs help devs and make money.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create your website with
Get started
<span>%d</span> bloggers like this: