Learn TypeScript

Using the unknown type

Using the unknown type

In this lesson, we will learn about the unknown type; it is similar to the any type but is type-safe.

An any type refresher

In a previous lesson, we learned that the any type could be used when we are unsure of the type of value. The problem with any is that no type checks will be carried out on values of type any.

What if there was a type like any that can be used for values we don't know but was also type-safe? This is what the unknown type is!

Understanding the unknown type

We are going to explore the unknown type in the exercise below.

TypeScriptOpen exercise in CodeSandbox

The code contains a function that adds the parameters together and returns the result. The parameters are of type unknown.

🤔

Do any type errors occur on the function?

Type checking does occur on the unknown type, unlike with the any type.

  • Update the function to have the implementation below:
1function add(a: unknown, b: unknown) {
2 if (typeof a === "number" && typeof b === "number") {
3 return a + b;
4 }
5 return 0;
6}
🤔

What are the types of a and b in the return statement on line 3?

The if statement on line 2 is called a type guard. The type guard allows TypeScript to adjust the types of a and b from unknown to number. Code within the if statement can then operate on a and b.

You can't operate directly on variables of type unknown. We have to give TypeScript information to narrow the type so that it can be used.

We will cover type guards later in this course. So, don't worry if you don't understand this fully yet. The key point is that we can't operate directly on variables of type unknown.

Type-safe data fetching

  • Copy the code below into the code editor:
1async function getData(path: string): Promise<unknown> {
2 const response = await fetch(path);
3 return await response.json();
4}
5
6type Person = {
7 id: string;
8 name: string;
9};
10
11async function getPerson(id: string): Promise<Person | null> {
12 const person = await getData("/people/1");
13 if (person) {
14 return person;
15 }
16 return null;
17}

The code gets a person object from a web API.

There is some syntax that we are not familiar with yet in the above code in the function’s return type annotations. We’ll learn about this syntax later in this course but for now, here’s an explanation of these return types:

  • The getData function returns a promise of type unknown.

  • The getPerson function returns a promise of type Person or null.

  • Focus on line 14, where the person variable is returned from the getPerson function.

🤔

A type error occurs on line 14. Why is this so?

We need to check that person on line 13 is in fact of type Person to resolve the type error. We can use a type predicate to check that an object is of type Person.

  • Add the following type predicate function:
function isPerson(person: any): person is Person {
return "id" in person && "name" in person;
}

Notice the return type, person is Person. This is a type predicate; it is a special return type that the Typescript compiler uses to know what type a particular value is. We’ll learn about type predicates in detail later in this course.

  • Add the isPerson function into the code editor and have a go at referencing it on line 13 to resolve the type error.

The type error disappears as we expect.

Summary

The unknown type allows us to reduce our use of any and create more strongly-typed code. We do write a little more code when using unknown, but the confidence we get from knowing our code is type-safe is well worth it.

Great stuff! Next, let's check what we have learned in this module with a quiz.

Did you find this lesson useful?

Share this lesson on twitter
© 2023 Carl Rippon
Privacy Policy
This site uses cookies. Click here to find out more