Type

TypeScript also has interface, however type can support Union, Partial and other Typescript API.

If you're not sure, use type

Example:

type Bet =
  | { kind: "single"; stakeCents: number }
  | { kind: "multi"; stakeCents: number; legs: number };

Note that the | before the first one just for presentation.

Don't use any, use unknown

function parseAmount(amount: unknown): number {
  if (typeof amount === "number" && Number.isInteger(amount) && amount > 0) {
    return amount;
  }

  throw new Error("amount must be positive");
}

If you use any here you would loose type check. Since any could be any type.

By forcing to be unknown, your code has to make sure it's the right type.

Generic type

function first<T>(items: readonly T[]): T | undefined {
  return items[0];
}

For safety check on items[0]

Note: in contrast to other language, js when we do items[0] and items is empty, it does not throw. However the items[0] could be undefined.

To make it safe for typescript to complains if items[0] could be undefined, we can set "noUncheckedIndexedAccess": true, in tsconfig.json for compiler option

{
    "compilerOptions": {
        "noUncheckedIndexedAccess": true,
    }
}