Taming TypeScript

The TypeScript Tutorial for The Hater

The Safe Alternative: `unknown`

The Problem with any

In the last lesson, we saw that any is a trap. It turns off TypeScript's safety features and lets potential runtime errors slip back into our code.

But what do you do when you genuinely don't know the type of a value? This happens often when working with third-party APIs, user input, or network responses.

You need a way to tell TypeScript, "I don't know what this is, but I want you to keep me safe." For this, we have unknown.

unknown: The Safe any

The unknown type is the type-safe counterpart to any. Like any, you can assign any value to a variable of type unknown.

let myValue: unknown;

myValue = "hello";
myValue = 123;
myValue = { name: "Luigi" };

Here's the crucial difference: you cannot do anything with an unknown value until you have proven what type it is.

Exercise 1: The unknown Wall

  1. The variable data is of type unknown.
  2. Try to call methods on it like .toUpperCase() or .toFixed().
  3. Notice that TypeScript gives you an error for every single one. It's protecting you because it can't guarantee that any of these methods exist on the data variable.
Interactive Editor
Loading...

This is the opposite of any. Instead of letting you do whatever you want, unknown prevents you from doing anything until you perform a type check.

How to Safely Use an unknown Value

To use a value of type unknown, you must first narrow its type to something more specific. We've already seen how to do this with union types: we use type guards like typeof.

The same principle applies to unknown.

Exercise 2: Safely Handling unknown

  1. The logValue function takes a parameter value of type unknown.
  2. Use typeof checks to handle the cases where value is a string or a number.
  3. Add an else block to handle any other type.
Interactive Editor
Loading...
Click to see the solution
function logValue(value: unknown) {
  if (typeof value === "string") {
    console.log(value.toUpperCase());
  } else if (typeof value === "number") {
    console.log(value.toFixed(2));
  } else {
    console.log("Not a string or number.");
  }
}

any vs. unknown: A Summary

This is a critical concept in TypeScript.

  • any: "I know best. Turn off type checking." This is unsafe.
  • unknown: "I don't know what this is. Force me to check its type before I use it." This is safe.

Always prefer unknown over any.

Using unknown forces you to build robust, defensive code that can handle unexpected inputs. It keeps the safety of the type system intact while still giving you the flexibility to work with data whose type you can't know in advance.