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
- The variable
datais of typeunknown. - Try to call methods on it like
.toUpperCase()or.toFixed(). - 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
datavariable.
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
- The
logValuefunction takes a parametervalueof typeunknown. - Use
typeofchecks to handle the cases wherevalueis astringor anumber. - Add an
elseblock to handle any other type.
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.