TypeScript's Unknown data type

TypeScript's Unknown data type

ยท

3 min read

There are data types in TypeScript that are better known than others. Today I would like to introduce a less known data type: unknown.

The unknown data type

The unknown type exists since TypeScript 3.0 (the current version is 4.2) and is a top type.

Similar to the any type, a variable of type unknown accepts values of any type.

The difference is that a value of type any can be assigned to variables of all types and a value of type unknown can only be assigned to variables of the type any or unknown.

/**
 * New variable of type unknown
 **/
let test: unknown;

/**
 * Assigning a value to an unknown variable
 **/
test = 'hello world';       // Works!
test = 5;                   // Works!
test = false;               // Works!
test = () => false          // Works!
test = new Audio();         // Works!

/**
 * Using an unknown variable
 **/
let myString: string = test;    // Error: Type 'unknown' is not assignable to type 'string'
let myBool: boolean = test;     // Error: Type 'unknown' is not assignable to type 'booelan'
const test2: unknown = test;    // Works!
const test3: any = test;        // Works!

test.foo(); // Error: Object is of type 'unknown'
new test(); // Error: Object is of type 'unknown'

When to use unknown?

unknown forces type checking and is safer than any. That's why its use should always be favored over any.

Here is an example with JSON.parse(), which always returns a value of type any.

In the following situation the code will compile without noticing that there is a huge error. The JSON string is not of type IPerson and should not be assignable to the variable phoebe.

interface IPerson {name: string, age: number}

const jsonString = '{"alias": "rose", "color": "red"}';

const person = JSON.parse(jsonString); // This returns any
const phoebe: IPerson = person; // This should throw a type error, but doesn't...

To make our code safer and catch the type error, we can use unknown in combination with a custom Type Guard.

interface IPerson {name: string, age: number}

const jsonString = '{"name": "rose", "age": 25}';

const person: unknown = JSON.parse(jsonString); // This returns any.
const notPerson: IPerson = person; // Error Type 'unknown' is not assignable to type 'IPerson'.

/** 
 * Create a custom Type Guard to make sure that
 * the parsed data is of type Person.
 */
const isPerson = (data: any): data is IPerson => {
    return typeof data.name == 'string' && typeof data.age == 'number'
}

/**
 * Use Type Guard.
 */
if(isPerson(person)){
    console.log('This is a person!');
    // With the Type Guard the assignement of the 
    // variable as type Person works.
    const phoebe: IPerson = person;
} else {
    throw Error('Parsed string is not a Person.')
}

Follow me on Hashnode, dev.to and twitter!


Credits