TypeScript Special Types: never, void, unknown, any
TypeScript has four special types: never, void, unknown, and any.
They play an important role in the type system. Understanding their differences is crucial for writing type-safe code.
SVG Diagram: Special Type Comparison
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 differences between these four special types helps us write safer and more accurate typed code.
Concept explanation:never, void, unknown, and any are TypeScript's special types, each with different meanings and use cases.
The never Type
never represents a type that never returns. It is usually used for functions that throw exceptions or loop infinitely.
Example
// The function never returns normally; it always throws an error
function throwError(message: string): never {
throw new Error(message);
}
// Function with an infinite loop
// The function never returns; the program keeps running
function infiniteLoop(): never {
while (true) {
console.log("Running...");
}
}
// never is a subtype of all types
// 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 赋值给 number: undefined
Important:never is a subtype of all types, which means never can be assigned to any type, but no type can be assigned to never (except never itself).
The void Type
void means there is no return value, and it is usually used to declare functions that have no return statement.
Example
// The function has no return value after execution
function logMessage(message: string): void {
console.log("Log: " + message);
// No return statement, or return undefined
}
logMessage("Hello");
// void variable (rarely used)
// Can only be assigned undefined
var empty: void = undefined;
console.log("void variable: " + empty);
Output:
日志: Hello void 变量: undefined
Explanation:void is actually very similar to undefined and is mainly used for function return type declarations, indicating that the function has no return value.
The unknown Type
unknown is a type-safe any. When using unknown, you must perform type checking before using it.
Example
// This is a "safe" any
var value: unknown = "hello";
value = 42;
value = true;
// An unknown type cannot be directly assigned to other types
// If you uncomment the next line, the compiler will report an error
// var str: string = value;
// It can only be assigned after type checking
if (typeof value === "string") {
// TypeScript knows value is of type string
var str: string = value;
console.log("String length: " + str.length);
}
Output:
字符串长度: 5
Safety:unknown enforces type checking before use, which protects type safety. When handling data from unknown sources, you should use unknown instead of any.
The any Type
any completely bypasses type checking and can be assigned any type. It is the least safe type in TypeScript.
Example
// 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);
// An object of type any can call any method
// The compiler won't report an error, but it may fail at runtime
var obj: any = {};
obj.foo(); // No error is reported, but the foo method does not actually exist
obj.bar = "value";
Warning:The any type completely bypasses TypeScript's type checking and should be avoided as much as possible. If it must be used, make sure the value's type is correct.
Comparing any vs unknown
Both any and unknown can accept any type, but their safety is completely different.
| Feature | any | unknown |
|---|---|---|
| Accepts any type | ✓ Yes | ✓ Yes |
| Directly assignable to other types | ✓ Yes | ✗ No (requires checking) |
| Directly calling methods | ✓ Yes | ✗ No (requires checking) |
| Type safety | ✗ None | ✓ Yes |
Recommendation:When processing data of unknown types, prefer using unknown over any, as this forces type checking.
never vs void
Both never and void are used for function return types, but their meanings are completely different.
| Feature | never | void |
|---|---|---|
| Meaning | Never returns | No return value |
| Used for functions | Throwing exceptions / infinite loops | Ordinary functions with no return value |
| Assignable to other types | ✓ Yes (subtype) | Only assignable to void/any |
Key difference:never means the function never returns normally (either it throws an exception or enters an infinite loop); void means the function executes normally but has no return value.
Practical Application: Exhaustive Check
An important use of the never type is to perform exhaustive checks, ensuring that all possible cases have been handled.
Example
type Shape = { kind: "circle", radius: number }
| { kind: "square", side: number };
// Calculate the area of a shape
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 you add a new Shape type but forget to handle it, the compiler will report an 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:
圆形面积: 78.54 正方形面积: 16
Exhaustive Check:This pattern ensures that when a new type branch is added, if you forget to handle it in the switch, the compiler will report an error because the new type cannot be assigned to never.
Notes
- never is a subtype:never can be assigned to any type, but no type can be assigned to never
- void vs undefined:In JavaScript, void and undefined are basically equivalent
- unknown requires checking:Before using a value of type unknown, you must perform type checking.
- Avoid any:Try not to use any; prefer unknown.
Best practices:Type safety from highest to lowest: never > void > unknown > any. Use safer types whenever possible.
Summary
Understanding these four special types is very important 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 that have no return value.
- unknown:Safe arbitrary type; must perform type checking before use.
- any:Bypasses all type checks; should be avoided as much as possible.
Other extensionsRecommendations:When writing code, prefer stricter types. Use unknown for unknown data, void for functions with no return value, and never when exhaustive checks are needed.