DEV Community

Cover image for A Comprehensive Guide to TypeScript’s `any`, `unknown`, and `never` Types
Dipak Ahirav
Dipak Ahirav

Posted on

A Comprehensive Guide to TypeScript’s `any`, `unknown`, and `never` Types

TypeScript is a superset of JavaScript that adds static type definitions, enabling developers to catch errors early during the development process. Among its many features, TypeScript includes several special types—any, unknown, and never—each serving a distinct purpose. Understanding the differences and proper use cases for these types is crucial for writing robust and maintainable code. This guide aims to provide a comprehensive overview of these types, highlighting their characteristics, use cases, and examples.

please subscribe to my YouTube channel to support my channel and get more web development tutorials.

The any Type

The any type is the most permissive type in TypeScript. It essentially disables type checking for a variable, allowing it to hold any value and enabling any operation to be performed on it.

Characteristics of any:

  • Disables Type Checking: Variables of type any can be assigned any value without type errors.
  • Maximum Flexibility: Useful for scenarios where the type is dynamic or unknown at compile time.
  • Potentially Unsafe: Overuse can lead to runtime errors and reduce the benefits of TypeScript's type system.

Example Usage:

let dynamicVar: any;

dynamicVar = 10; // Valid
dynamicVar = "Hello"; // Valid
dynamicVar = true; // Valid

console.log(dynamicVar.toUpperCase()); // No compile-time error, but may cause runtime error if dynamicVar is not a string
Enter fullscreen mode Exit fullscreen mode

Appropriate Use Cases:

  • Interfacing with Third-Party Libraries: When using libraries without TypeScript definitions.
  • Prototyping: Rapidly prototyping code where types are not yet established.

The unknown Type

Introduced in TypeScript 3.0, the unknown type is a safer alternative to any. It represents a value that could be of any type, but unlike any, it requires explicit type checking before use.

Characteristics of unknown:

  • Type-Safe: Requires type assertions or checks before performing operations.
  • Encourages Safer Code: Prevents unintended operations by enforcing type checks.

Example Usage:

let uncertainVar: unknown;

uncertainVar = 10; // Valid
uncertainVar = "Hello"; // Valid

if (typeof uncertainVar === "string") {
  console.log(uncertainVar.toUpperCase()); // Safe
} else {
  // This would cause a compile-time error
  // console.log(uncertainVar.toUpperCase()); // Error
}
Enter fullscreen mode Exit fullscreen mode

Appropriate Use Cases:

  • Handling External Data: Processing values from APIs or user inputs where the type is not guaranteed.
  • Generic Programming: Writing functions that handle various types with runtime type checks.

The never Type

The never type represents values that never occur. It is used to indicate that a function never returns a value, either because it always throws an exception or it enters an infinite loop.

Characteristics of never:

  • Represents Unreachable Code: Used in functions that do not complete normally.
  • Subtype of Every Type: never can be assigned to any type, but no type can be assigned to never.

Example Usage:

function throwError(message: string): never {
  throw new Error(message);
}

function infiniteLoop(): never {
  while (true) {
    // Loop forever
  }
}

function fail(): never {
  return throwError("Something went wrong!");
}
Enter fullscreen mode Exit fullscreen mode

Appropriate Use Cases:

  • Error Handling: Functions that throw exceptions to indicate errors.
  • Infinite Loops: Functions designed to run indefinitely.
  • Exhaustiveness Checking: Ensuring all possible cases are handled in a switch statement or union type.

Exhaustiveness Checking Example:

type Shape = 
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number };

function getArea(shape: Shape): number {
  switch (shape.kind) {
    case "circle":
      return Math.PI * shape.radius ** 2;
    case "square":
      return shape.side ** 2;
    default:
      // Ensures all cases are handled
      const _exhaustiveCheck: never = shape;
      throw new Error(`Unhandled shape: ${_exhaustiveCheck}`);
  }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

Understanding the distinctions between any, unknown, and never is essential for leveraging TypeScript's type system effectively. Using any provides flexibility at the cost of type safety, while unknown offers a balance by enforcing type checks. The never type, though less commonly used, is vital for indicating unreachable code and ensuring exhaustive checks. By applying these types appropriately, developers can write more predictable, maintainable, and robust TypeScript code.

Follow me for more tutorials and tips on web development. Feel free to leave comments or questions below!

Follow and Subscribe:

Top comments (0)