Top Types and Bottom Types
In the previous chapter, we expanded our understanding of types with narrowing, widening, and immutability using const assertions. In this chapter, we will explore TypeScript’s top types (any and unknown), the bottom type (never), and the special type (void).
Illustration:

Top Types: any and unknown
The Flexibility of any
The any type is a universal type that can hold any value. While this provides flexibility, it disables type checking, which can lead to runtime errors. Here’s an example:
function logName(user: any) {
console.log(user.props.name);
}
logName({ props: { name: 'Benny' } }); // Works
logName({}); // Crashes because 'props' is missingThe TypeScript team strongly advises against using any unless transitioning a JavaScript codebase to TypeScript. For safer alternatives, let’s explore unknown.
The Power of unknown
Introduced in TypeScript 3.0, unknown is a type-safe alternative to any. It requires developers to narrow down the type using control flow before accessing its properties:
function logName(user: unknown) {
if (
typeof user === 'object' &&
user !== null &&
'props' in user &&
typeof user.props === 'object' &&
'name' in user.props
) {
const name = user.props.name;
if (typeof name === 'string') {
console.log(name);
}
}
}
logName({ props: { name: 'Benny' } }); // Logs "Benny"
logName({}); // Safely does nothingBy enforcing these checks, unknown ensures type safety and prevents runtime crashes.
Practical Use of unknown
In testing scenarios, mock objects often replace real implementations. Type assertions with unknown can help circumvent strict type checks temporarily:
import { jest } from '@jest/globals';
import { Client } from 'typesense';
const client = {
health: {
retrieve: jest.fn(),
},
} as unknown as Client;This approach strips type information with unknown before reasserting the desired type.
Bottom Type: never
The never type represents values that never occur. It’s typically used for unreachable code or exhaustive checks in TypeScript:
Example:
type StreamStatus = 'ONLINE' | 'OFFLINE';
function handleResponse(status: StreamStatus): void {
switch (status) {
case 'ONLINE':
console.log('Stream is online.');
break;
case 'OFFLINE':
console.log('Stream is offline.');
break;
default:
const neverStatus: never = status;
throw new Error(`Unhandled status: ${neverStatus}`);
}
}By leveraging never in the default case, TypeScript ensures that all possible cases are handled. Adding a new status, like "IDLE", would trigger a compile-time error until it is explicitly handled.
No Type: void
The void type represents the absence of a return value. It is commonly used for functions that perform actions without returning anything:
function logMessage(message: string): void {
console.log(message);
}Comparison: void and undefined
While void and undefined may seem similar, they have distinct purposes. A function with an undefined return type must explicitly return undefined, while a void function does not:
function doNothing(): undefined {
return undefined;
}
function logNothing(): void {
// No return statement needed
}In scenarios where the return value is irrelevant, void is preferred to communicate the lack of interest in the return type.
What You Have Learned
Top Types: any and unknown: You have learned about TypeScript’s top types, any and unknown. The any type allows a variable to hold any value to mimic JavaScript’s standard behaviour, potentially causing runtime errors. The unknown type, introduced in TypeScript 3.0, provides a safer alternative by requiring explicit type narrowing before accessing properties, ensuring type safety.
Bottom Type: never: You now understand that the never type represents values that never occur. It’s useful for situations like unreachable code or exhaustive checks, ensuring that all possible cases are handled in TypeScript.
No Type: void: You’ve learned that the void type is used for functions that do not return a value. It signals the absence of a return value, distinguishing it from undefined, which requires explicit returning of undefined. The void type is useful in your code to indicate that the return value is not important or relevant.
Quiz
- Which statement best describes the
anytype in TypeScript?
- a) It allows you to assign only
stringandnumbervalues. - b) It is the safest type for any unknown data structure.
- c) It can hold any value and was designed to mimic JavaScript's original type behaviour.
- d) It restricts object properties to a known subset.
- What must you do before accessing properties on a variable typed as
unknown?
- a) Assign it to an intermediate variable of type
any. - b) Perform type checks or narrowing to confirm its structure.
- c) Cast it to
stringand then access properties. - d) Nothing,
unknownbehaves exactly likeany.
- How is the
nevertype typically used in TypeScript?
- a) For return values of functions that never return.
- b) For variables that can accept any type of value.
- c) For optional properties in interfaces.
- d) As a shorthand for
undefinedin TypeScript.
- What does TypeScript enforce if you include a
nevertype in a switch statement’s default case?
- a) It allows partial coverage of cases without error.
- b) It automatically converts all other cases to
any. - c) It ensures all possible cases are exhaustively handled.
- d) It disables type checking within the
switchblock.
- Which statement correctly explains the difference between
voidandundefinedin a function return type?
- a) A function returning
voidmust explicitly returnundefined. - b) Both
voidandundefinedrequire a return statement. - c) Using
voidindicates no meaningful return value;undefinedmeans the function must explicitly returnundefined. - d)
voidis only valid in strict mode, whereasundefinedis not.
- Which approach ensures runtime immutability for an object in JavaScript in addition to TypeScript compile-time checks?
- a) Declaring the object with
unknown. - b) Using
as constin TypeScript, which automatically freezes the object at runtime. - c) Calling
Object.freeze()on the object in strict mode. - d) Specifying the object’s type as
neverto prevent reassignment.
