TypeScript Special Types
Understanding any, unknown, and never types
⚡ Special Types in TypeScript
TypeScript has three special types: any (disables type checking), unknown (type-safe any), and never (represents values that never occur). These handle edge cases where standard types don't fit perfectly.
let flexible: any = "anything";
let safe: unknown = "needs checking";
function error(): never {
throw new Error("Never returns");
}
Three Special Types
any
Disables type checking
let data: any = 5;
data = "text"; // OK
data = true; // OK
unknown
Type-safe version of any
let value: unknown = 5;
// Must check type first
if (typeof value === "number") {
console.log(value + 1);
}
never
Represents impossible values
function fail(): never {
throw new Error("Failed");
}
🔹 The any Type
The any type disables type checking - use sparingly:
// any allows anything
let value: any = 10;
value = "Hello"; // OK
value = true; // OK
value = [1, 2, 3]; // OK
// No type checking on operations
let result: any = "5";
console.log(result * 2); // No error, but outputs: NaN
// Use case: Working with dynamic data
let userInput: any = getUserInput(); // From external source
Output:
NaN
⚠️ Warning:
Using any defeats the purpose of TypeScript. Only use it when absolutely necessary!
🔹 The unknown Type
unknown is safer than any - requires type checking before use:
// unknown requires type checking
let userInput: unknown = "Hello";
// ❌ Error: Can't use directly
// console.log(userInput.toUpperCase());
// ✅ Correct: Check type first
if (typeof userInput === "string") {
console.log(userInput.toUpperCase()); // OK
}
// Another example
let data: unknown = 42;
if (typeof data === "number") {
console.log(data + 10); // Output: 52
}
Output:
HELLO
52
🔹 The never Type
never represents values that never occur:
// Function that never returns
function throwError(message: string): never {
throw new Error(message);
}
// Infinite loop never returns
function infiniteLoop(): never {
while (true) {
console.log("Running forever...");
}
}
// Practical use: Exhaustive checking
type Shape = "circle" | "square";
function getArea(shape: Shape): number {
switch (shape) {
case "circle":
return 3.14;
case "square":
return 4;
default:
// This should never happen
const exhaustive: never = shape;
throw new Error(`Unhandled shape: ${exhaustive}`);
}
}
🔹 Comparing Special Types
Understanding when to use each type:
any vs unknown:
// any: No safety
let anyValue: any = "text";
anyValue.toUpperCase(); // Works
anyValue.nonExistent(); // No error (but fails at runtime!)
// unknown: Type-safe
let unknownValue: unknown = "text";
// unknownValue.toUpperCase(); // Error: Must check type first
if (typeof unknownValue === "string") {
unknownValue.toUpperCase(); // OK
}
📊 Quick Comparison:
- any: Opt-out of type checking (use rarely)
- unknown: Type-safe any (preferred over any)
- never: Functions that never return or impossible values
🔹 Practical Examples
Real-world usage of special types:
Example 1: API Response (unknown)
// Handling API data safely
function processAPIResponse(response: unknown) {
if (typeof response === "object" && response !== null) {
console.log("Valid object received");
// Further processing...
} else {
console.log("Invalid response");
}
}
processAPIResponse({ name: "Alice" }); // Valid object received
processAPIResponse("invalid"); // Invalid response
Example 2: Error Handler (never)
// Utility function that always throws
function assertNever(value: never): never {
throw new Error(`Unexpected value: ${value}`);
}
type Status = "success" | "error";
function handleStatus(status: Status) {
switch (status) {
case "success":
console.log("Success!");
break;
case "error":
console.log("Error!");
break;
default:
assertNever(status); // Ensures all cases handled
}
}
🔹 Best Practices
✅ Do:
- Use unknown instead of any when possible
- Use never for functions that throw errors
- Always check types before using unknown values
- Use never for exhaustive type checking
❌ Don't:
- Use any unless absolutely necessary
- Use unknown without type guards
- Assign values to never type variables
- Ignore TypeScript errors by using any