typescript

Conditional narrowing of the `any` type in TypeScript

December 13, 2022

A variable of the any type can be any value. It's an "escape hatch" that brings us back to dynamically typed JavaScript. The any type should generally be avoided.

A value with the any type can be assigned to any variable, regardless of that variable's type.

const myNum: any = 11;
const myStr: string = myNum;
console.log(myStr); // 11

View in TS Playground

Here is another example:

const user: any = { name: 'Joseph' };
const numbers: number[] = user;
console.log(numbers); // { name: 'Joseph' }

View in TS Playground

Neither of these examples throw a type error even though we are assigning values to variables with the incorrect type. This defeats the very purpose of TypeScript and can lead to bugs down line.

So what do we do when we encounter the any type in the wild?

For example, we could be using a third party library. Imagine we have a function that tells us whether or not a user is active. Because the library is poorly typed the function returns true or false with the any type.

function isUserActive(): any {
return true;
}

We can use a type guard and conditional narrowing to bring the value back into the land of static types.

function checkStatusType(status: any): boolean {
if (typeof status === 'boolean') {
return status;
} else {
throw new Error(`${status} is a ${typeof status}, not a boolean`);
}
}

We use typeof to check type of the argument and throw an error when the function is passed a value that is not the type we expect it to return (in our case, a boolean).

Let's test this by assigning a string value to a variable with the any type, and pass it to our type guard function.

const userStatus: any = 'true';
const checkedUserStatus: boolean = checkStatusType(userStatus);
console.log(checkedUserStatus) // Error: false is a string, not a boolean

Now let's try this again, with the function from the third party library that returns true or false as the any type.

const userStatus: any = isUserActive();
const checkedUserStatus: boolean = checkStatusType(userStatus);
console.log(checkedUserStatus) // true

It works. We now have the correct type.

Now when we try to assign our checkedUserStatus variable to a variable with a different type, we get a type error.

const storeUserStatus: string = checkedUserStatus;
// Type 'boolean' is not assignable to type 'string'.

View in TS Playground

I've updated my super simple UI component library on NPM

Previous

Updating a GatsbyJS website: breaking changes everywhere

Next

© 2023. Made with ❤️ for Max 👶🏻.