TypeScript Special Types: never, void, unknown, any | Tutorial
TypeScript has four special types: never, void, unknown, and any.
They play important roles in the type system, and understanding their differences is crucial for writing type-safe code.
Why Special Types Are Needed
TypeScriptβs type system is very powerful. In addition to regular types, it provides four special types to handle specific scenarios.
Understanding the distinctions among these four special types helps us write safer and more accurate type code.
Concept Explanation:
never,void,unknown, andanyare TypeScriptβs special types, each with distinct meanings and use cases.
never Type
never represents a type that never returns. It is typically used for functions that throw exceptions or run infinite loops.
Example
// Function that throws an exception
// Function never returns normally; always throws an error
function throwError(message: string): never {
throw new Error(message);
}
// Function with infinite loop
// Function never returns; program runs indefinitely
function infiniteLoop(): never {
while (true) {
console.log("Running...");
}
}
// never is a subtype of every type
// This means never can be assigned to any type
var neverValue: never;
var num: number = neverValue; // Correct: never is a subtype of number
console.log("never assigned to number: " + num);
Output:
never assigned to number: undefined
Important:
neveris a subtype of every type, meaningnevercan be assigned to any type, but no type (exceptneveritself) can be assigned tonever.
void Type
void indicates no return value and is commonly used for functions without a return statement.
Example
// Function with no return value
// Function executes without returning a value
function logMessage(message: string): void {
console.log("Log: " + message);
// No return statement, or return undefined implicitly
}
logMessage("Hello");
// void variable (rarely used)
// Can only be assigned undefined
var empty: void = undefined;
console.log("void variable: " + empty);
Output:
Log: Hellovoid variable: undefined
Note:
voidis essentially similar toundefinedand is primarily used to declare function return types, indicating the function has no return value.
unknown Type
unknown is a type-safe version of any. When using unknown, type checking must be performed before usage.
Example
// unknown accepts any type
// This is the "safe" any
var value: unknown = "hello";
value = 42;
value = true;
// Unknown type cannot be directly assigned to other types
// Uncommenting the next line would cause a compiler error
// var str: string = value;
// Type checking required before assignment
if (typeof value === "string") {
// TypeScript knows value is of type string
var str: string = value;
console.log("String length: " + str.length);
}
Output:
String length: 5
Security:
unknownenforces type checking before usage, safeguarding type safety. When handling data from unknown sources, useunknowninstead ofany.
any Type
any completely bypasses type checking and can be assigned any type. It is the least safe type in TypeScript.
Example
// any can be any type
// Completely bypasses type checking
var anything: any = "hello";
anything = 42;
anything = true;
// any can be assigned to any type
// This breaks type safety
var str: string = anything;
var num: number = anything;
console.log("String: " + str);
console.log("Number: " + num);
// Methods can be called on any-type objects without compiler errors
// Compiler won't complain, but runtime errors may occur
var obj: any = {};
obj.foo(); // No compile error, but foo method does not actually exist
obj.bar = "value";
Warning:
anycompletely bypasses TypeScriptβs type checking and should be avoided whenever possible. If usage is unavoidable, ensure the valueβs type is correct.
Comparison: any vs unknown
Both any and unknown accept any type, but their safety levels differ significantly.
| Feature | any | unknown |
|---|---|---|
| Accepts any type | β Yes | β Yes |
| Directly assignable to other types | β Yes | β No (requires checking) |
| Direct method invocation | β Yes | β No (requires checking) |
| Type safety | β None | β Yes |
Suggestion: When handling data of unknown type, prefer
unknownoveranyto enforce type checking.
never vs void
Both never and void are used for function return types, but their meanings differ significantly.
| Feature | never | void |
|---|---|---|
| Meaning | Never returns | No return value |
| Used for functions | Throwing exceptions / infinite loops | Ordinary functions without return value |
| Assignable to other types | β Yes (subtype) | Only to void / any |
Key Difference:
nevermeans the function never returns normally (either throws an exception or enters an infinite loop);voidmeans the function completes normally but returns no value.
Practical Application: Exhaustive Check
A key use case of never is exhaustive checking to ensure all possible cases are handled.
Example
// Define a union type for shapes
type Shape = { kind: "circle", radius: number }
| { kind: "square", side: number };
// Calculate shape area
function area(shape: Shape): number {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.side ** 2;
default:
// The default branch should handle all unexpected cases
// If a new Shape type is added but not handled, the compiler will error
var _exhaustive: never = shape;
return _exhaustive;
}
}
var circle = { kind: "circle" as const, radius: 5 };
var square = { kind: "square" as const, side: 4 };
console.log("Circle area: " + area(circle).toFixed(2));
console.log("Square area: " + area(square));
Output:
Circle area: 78.54Square area: 16
Exhaustive Check: This pattern ensures that if a new type branch is added but not handled in the
switch, the compiler will error because the new type cannot be assigned tonever.
Notes
- never is a subtype:
nevercan be assigned to any type, but no type can be assigned tonever - void vs undefined: In JavaScript,
voidandundefinedare essentially equivalent - unknown requires checking: Before using a value of type
unknown, type checking must be performed - Avoid any: Avoid using
anywhenever possible; preferunknown
Best Practice: In terms of type safety (from highest to lowest):
never>void>unknown>any. Prefer safer types whenever possible.
Summary
Understanding these four special types is essential for writing high-quality TypeScript code.
- never: Never returns; used for exhaustive checks; is a subtype of all types
- void: No return value; used for ordinary functions without a return value
- unknown: Type-safe βanyβ type; requires type checking before use
- any: Bypasses all type checking; should be avoided whenever possible
Suggestion: When writing code, prefer stricter types. Use
unknownfor unknown data,voidfor functions without return values, andneverfor exhaustive checks.
YouTip