YouTip LogoYouTip

Ts Special Types

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, and any are 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: never is a subtype of every type, meaning never can be assigned to any type, but no type (except never itself) can be assigned to never.



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: void is essentially similar to undefined and 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: unknown enforces type checking before usage, safeguarding type safety. When handling data from unknown sources, use unknown instead of any.



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: any completely 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 unknown over any to 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: never means the function never returns normally (either throws an exception or enters an infinite loop); void means 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 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 essentially equivalent
  • unknown requires checking: Before using a value of type unknown, type checking must be performed
  • Avoid any: Avoid using any whenever possible; prefer unknown

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 unknown for unknown data, void for functions without return values, and never for exhaustive checks.

← Ts Function OverloadTs Null Undefined β†’