The unknown
type in TypeScript is a safe, flexible way to handle variables with uncertain types. Unlike any
, which allows any kind of operations without restriction, unknown
provides a type-safe alternative that requires type-checking before use. This tutorial will cover the basics of the unknown
, walk through detailed examples, and show you when and how to use it effectively.
TypeScript’s unknown
type is a safer alternative to any
, allowing you to work with dynamic data without sacrificing type safety. It encourages type-checking and validation, making your code more reliable and reducing potential runtime errors. This tutorial will explain how to use unknown
effectively, how it differs from any, and provide practical examples to demonstrate its value.
In TypeScript, the unknown
type represents a variable whose type is not known at the time of declaration. Unlike any
, the unknown
type requires type-checking before you can perform operations on the variable, making it a safer choice for handling uncertain data.
let data: unknown;
data = "Hello, TypeScript!";
data = 42;
data = { name: "Alice" };
Here:
unknown
, allowing it to hold any value.data
, but you must validate its type before using it in a type-specific way.unknown
With unknown
, TypeScript enforces type-checking before allowing certain operations, encouraging safer coding practices. You can use typeof
or custom type assertions to check the type.
typeof
let value: unknown = "Hello, World!";
if (typeof value === "string") {
console.log(value.toUpperCase()); // Safe to use as a string
}
In this example:
value
is declared as unknown
, so we must check if it’s a string before calling toUpperCase()
.toUpperCase()
unless the type is confirmed.Here are some scenarios where unknown
can be used effectively.
function processInput(input: unknown) {
if (typeof input === "string") {
console.log(`String input: ${input.toUpperCase()}`);
} else if (typeof input === "number") {
console.log(`Number input: ${input.toFixed(2)}`);
} else {
console.log("Unknown input type");
}
}
processInput("TypeScript"); // Output: String input: TYPESCRIPT
processInput(3.14159); // Output: Number input: 3.14
In this example:
processInput
function accepts input of type unknown
.any
and unknown
While any
and unknown
might seem similar, they behave very differently in TypeScript. Here’s a comparison:
Feature |
|
|
Type Safety |
No type safety (any operation is allowed) |
Enforces type-checking before usage |
Flexibility |
Maximum flexibility; allows all operations |
Allows flexible assignment, restricts usage |
Ideal Use Cases |
Legacy code, third-party libraries |
Handling uncertain or dynamic data safely |
Type Checking Required |
No |
Yes |
Using unknown
encourages you to validate the type, whereas any
permits unchecked operations, which can lead to runtime errors.
When working with API data where the response structure may vary, using unknown ensures that your code handles different types safely.
function handleApiResponse(response: unknown) {
if (typeof response === "object" && response !== null) {
if ("message" in response) {
console.log("Message:", (response as { message: string }).message);
} else {
console.log("Response does not contain a message");
}
} else {
console.log("Unexpected response type");
}
}
handleApiResponse({ message: "Hello, World!" }); // Output: Message: Hello, World!
handleApiResponse("Invalid Response"); // Output: Unexpected response type
In this example:
handleApiResponse
function accepts response of type unknown
.object
and if it has a message property, ensuring safe handling of dynamic data.When processing user-defined data where the input type is uncertain, unknown helps enforce type-checking.
function printValue(value: unknown) {
if (Array.isArray(value)) {
console.log("Array:", value.join(", "));
} else if (typeof value === "string") {
console.log("String:", value);
} else if (typeof value === "number") {
console.log("Number:", value.toFixed(2));
} else {
console.log("Unknown type");
}
}
printValue([1, 2, 3]); // Output: Array: 1, 2, 3
printValue("Hello World"); // Output: String: Hello World
printValue(42.5678); // Output: Number: 42.57
In this example:
printValue
function uses unknown
to accept any input and applies different logic depending on the type.typeof
, instanceof, or custom type guards before performing type-specific operations.
function handleInput(input: unknown) {
if (typeof input === "number") {
console.log("Number:", input.toFixed(2));
}
}
let data: unknown = "Hello";
let message: string = data as string; // Type assertion
unknown
type provides flexibility while enforcing type-checking, making it a safer alternative to any
.typeof
, instanceof
, or custom type guards is essential when working with unknown
.unknown
allows dynamic assignment without sacrificing control, making it ideal for handling uncertain data structures.unknown
type is particularly useful for dynamic API responses, user-defined data, and input validation.any
in favor of unknown
for handling uncertain data, as it promotes safer, more reliable code.The unknown
type in TypeScript is a flexible yet safe way to handle variables when the type isn’t immediately known. It encourages type-checking, making your code more predictable and less prone to runtime errors. In this tutorial, we explored the difference between unknown
and any
, detailed examples, and best practices for using unknown
effectively. By understanding and applying unknown
properly, you can handle uncertain data in TypeScript with confidence and reliability.