Introduction

What are Any and Unknown in TypeScript?

The Any Type as a Top Type

A top type is a universal type that acts as a parent type to other types. In the context of TypeScript, the type Any can represent any other type. Any can represent String, Number, Object, and other types available in TypeScript.

What if a function assigned to an object does not exist, but we want to call it?

let obj: any = { x: 0 };

obj.foo(); // no compiler error

What if we want to call a variable of type Any?

let obj: any = { x: 0 };

obj(); // no compiler error

What if we initialize a new property on the obj object?

let obj: any = { x: 0 };

obj.bar = '100'; // no compiler error

What if we assign a different value to the obj variable?

let obj: any = { x: 0 };

obj = "test"; // no compiler error

What if we assign the value of obj to another variable with a specified type?

let obj: any = { x: 0 };

const n: number = obj; // no compiler error

noImplicitAny

Sometimes, the TypeScript compiler is unable to infer the type from the context of the written code. In such cases, the default type that is assigned is any. To prevent this and increase type safety, we can add a flag called --noImplicitAny to the command that runs TypeScript compilation. This flag can also be added to the tsconfig.json file with a value of true. Adding this flag will cause a compiler error, informing us that implicit any type annotations are not allowed on variables, function parameters, etc. You get the idea.

noImplicitAny: true,

Example code with the noImplicitAny flag enabled:

// the compiler will notify us of an error
function fn(s) { // Parameter 's' implicitly has an 'any' type.
  console.log(s.subtr(3));
}

fn(42);

The Unknown Type as a Top Type (Surprisingly, a Second Top Type)

The Unknown type is a safer way to manage variable values, function parameters, etc. It requires that we first check the type of the variable or parameter.

Here are some ways to handle the Unknown type:

Type Assertion

function func(value: unknown) {
  value.toFixed(2); // compiler notifies of an error

  // Type assertion
  // compiler does not notify of an error
  (value as number).toFixed(2);
}

Value Comparison

function func(value: unknown) {
  value * 5; // compiler notifies of an error

  if (value === 123) { // comparison
    value * 5; // compiler does not notify of an error
  }
}

Type guards

function func(value: unknown) {
  value.length; // compiler notifies of an error

  if (typeof value === 'string') { // type guard
    value.length; // compiler does not notify of an error
  }
}

Assertion functions

function func(value: unknown) {
  value.test('abc'); // compiler notifies of an error

  assertIsRegExp(value);

  value.test('abc'); // compiler does not notify of an error
}

function assertIsRegExp(arg: unknown): asserts arg is RegExp {
  if (! (arg instanceof RegExp)) {
    throw new TypeError('Not a RegExp: ' + arg);
  }
}

Sources