Type 'unknown' is not assignable to type in TypeScript

avatar

Borislav Hadzhiev

Last updated: Jul 25, 2022

banner

Photo from Unsplash

Type 'unknown' is not assignable to type in TypeScript #

The "Type 'unknown' is not assignable to type" error occurs when we try to assign a value with a type of unknown to a value of a different type. To solve the error, use a type assertion or a type guard to verify that the two values have compatible types before the assignment.

Here is an example of how the error occurs.

index.ts
const a: unknown = 'James'; // ⛔️ Error: Type 'unknown' is // not assignable to type 'string'.ts(2322) const b: string = a;

The a variable has a type of unknown.

This often happens when fetching data from a remote API, because TypeScript doesn't know the shape of the values we're working with.

The unknown type is the type-safe counterpart of any.

If you are certain that the specific value has a compatible type, but TypeScript doesn't know about it, use a type assertion, e.g. value as RightType.

index.ts
const a: unknown = 'James'; const b: string = a as string;

Type assertions are used when we have information about the type of a value that TypeScript can't know about.

We effectively tell TypeScript that the a variable will be a string and not to worry about it.

Now that the values on the left and right-hand sides have compatible types, the assignment doesn't cause the error.

An alternative solution is to use a type guard.

index.ts
const a: unknown = 'James'; let b = ''; if (typeof a === 'string') { b = a; } console.log(b); // 👉️ "James"

We explicitly check if the variable a stores a value of type string before making the assignment.

TypeScript knows that once we're in the if block, the variable a is guaranteed to be a string.

When working with the unknown type, we basically tell TypeScript - we're going to get this value, but we don't know its type. We are just going to check with a couple of if statements to track it down and use it safely. In the if blocks, give us support for the particular type that is checked for.

Here is an example of how you would use a type guard when working with objects.

index.ts
const person: unknown = { name: 'James', country: 'Chile', }; type Person = { name: string; country: string; }; // 👇️ checks if obj has properties of Person function isPerson(obj: any): obj is Person { return ( typeof obj === 'object' && obj !== null && 'name' in obj && 'country' in obj ); } let james: Person; if (isPerson(person)) { // 👉️ person has type of Person here james = person; } else { james = { name: '', country: '' }; } console.log(james); // 👉️ {name: 'James', country: 'Chile'}

We used a user-defined type guard to check if an object has all of the properties of the Person type.

The obj is Person syntax is a type predicate where obj must be the name of the parameter the function takes.

If the isPerson function returns true, TypeScript knows that the passed in value is of type Person and allows us to assign it to the variable.

The example above simply checks if the passed in value is an object and contains the name and country properties.

We also had to check for null, because in JavaScript (and TypeScript), typeof null returns "object".

If the person variable doesn't store a value of a compatible type, we use default values.

You could also set the default values upon initializing the variable.

index.ts
const person: unknown = { name: 'James', country: 'Chile', }; type Person = { name: string; country: string; }; // 👇️ set defaults upon initialization let james: Person = { name: '', country: '', }; // 👇️ checks if obj has properties of Person function isPerson(obj: any): obj is Person { return ( typeof obj === 'object' && obj !== null && 'name' in obj && 'country' in obj ); } if (isPerson(person)) { // 👉️ person is type Person here james = person; } // 👇️ {name: 'James', country: 'Chile'} console.log(james);

Whether you are able to use this approach depends on your use case.

The goal is to make sure that the values on the left-hand and right-hand sides of the assignment have compatible types.

Here is an example of how to use a type guard to check if a value of type unknown is an array.

index.ts
const data: unknown = [ { name: 'James', country: 'Chile', }, { name: 'Alice', country: 'Germany', }, ]; type Person = { name: string; country: string; }; let people: Person[] = []; if (Array.isArray(data)) { people = data as Person[]; } // [ // { name: 'James', country: 'Chile' }, // { name: 'Alice', country: 'Germany' } // ] console.log(people);

We used the Array.isArray() method to check if the data variable stores an array before the assignment.

You might have to be more strict and check if the array has any elements and whether they contain specific properties, etc.

Conclusion #

To solve the "Type 'unknown' is not assignable to type" TypeScript error, use a type assertion or a type guard to verify that the two values have compatible types before the assignment. The error is caused when a value of type unknown is assigned to a value that expects a different type.

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.