Basic Types in TypeScript

Introduction

TypeScript’s type system starts with a small set of primitive and structural types you use everywhere: numbers, strings, booleans, arrays, tuples, enums, and a few special types for “anything,” “nothing,” and “no return.” This chapter shows how to annotate values, when each type fits, and pitfalls to avoid (especially any).

Prerequisites

  • Your First TypeScript Program
  • A project with strict: true in tsconfig.json (recommended)
  • Familiarity with JavaScript values (strings, arrays, null)

Primitive Types: number, string, boolean

TypeExamplesNotes
number42, 3.14, NaNAll JS numbers are IEEE doubles; no separate int
string"hi", 'a', `tpl`Same string type for all quote styles
booleantrue, falseNot truthy/falsy types—only the two literals
typescript
const count: number = 10;
const label: string = "items";
const active: boolean = true;
 
const total: number = count * 2;
const summary: string = `${label}: ${total}`;

Code explanation:

  • Annotations after : describe what may be stored in the variable
  • Operations that mix incompatible types (for example count + label) are rejected at compile time

Arrays

Two equivalent forms:

typescript
// Element type followed by []
const scores: number[] = [90, 85, 88];
 
// Generic Array<Element>
const tags: Array<string> = ["ts", "types"];

Code explanation:

  • number[] and Array<number> mean the same thing; pick one style per project
  • Empty arrays often need a hint: const ids: number[] = []

Multidimensional arrays:

typescript
const matrix: number[][] = [
  [1, 2],
  [3, 4],
];

Tuples: Fixed-Length, Typed Positions

A tuple is an array with a known length and type per index:

typescript
const pair: [string, number] = ["age", 30];
 
const name = pair[0];
const value = pair[1];

Code explanation:

  • Index 0 is string, index 1 is number
  • Assigning pair[1] = "thirty" fails type-checking

Optional tuple elements (TypeScript 4+):

typescript
const row: [string, number?] = ["id"];

Use tuples for small, ordered records (RGB, key-value pairs). For named fields, prefer objects and interfaces (later chapters).

Enums

Enums give names to related constants.

Numeric enum

typescript
enum Direction {
  Up,
  Down,
  Left,
  Right,
}
 
const move: Direction = Direction.Up;

Code explanation:

  • Members default to 0, 1, 2, ... unless you set values
  • Direction.Up is a number at runtime

String enum

typescript
enum LogLevel {
  Info = "INFO",
  Warn = "WARN",
  Error = "ERROR",
}
 
function log(level: LogLevel, text: string): void {
  console.log(`[${level}] ${text}`);
}
 
log(LogLevel.Info, "Server started");

Tip

Prefer const Objects in Modern Code

Many teams use as const objects instead of enum to avoid extra runtime code. Enums remain common in tutorials and legacy codebases—you should recognize them.

Special Types Overview

TypeMeaningTypical use
anyOpt out of checkingLegacy migration (avoid in new code)
unknownSafe top type—must narrow before useUser input, JSON parse
voidNo useful return valueFunctions that only side-effect
nullAbsence of valueExplicit null
undefinedUninitialized / missingOptional parameters, missing props
neverNo possible valueExhaustive checks, functions that always throw

void

For functions that do not return a meaningful value:

typescript
function logMessage(text: string): void {
  console.log(text);
}

void is not the same as undefined in all strictness settings, but callers usually ignore the return. You will refine return types in the functions chapter.

null and undefined

With strictNullChecks (part of strict: true), null and undefined are not assignable to other types unless you allow them:

typescript
let title: string = "Draft";
// title = null;  // Error under strictNullChecks
 
let subtitle: string | null = null;
subtitle = "Optional line";

Code explanation:

  • string | null is a union: either a string or null
  • Unions are covered in depth later; here they model optional values explicitly

any: Escape Hatch (Use Sparingly)

typescript
let data: any = fetchSomething();
data.foo.bar(); // No compile-time error—unsafe

any disables checking for that value. It propagates easily and hides bugs.

Warning

Avoid any in New Code

Prefer unknown or proper interfaces. Use any only for incremental migration with a plan to remove it.

unknown: Type-Safe “I Don’t Know Yet”

typescript
function parseJson(input: string): unknown {
  return JSON.parse(input);
}
 
const value = parseJson('{"count": 3}');
 
// value.count;  // Error: 'value' is of type 'unknown'
 
if (typeof value === "object" && value !== null && "count" in value) {
  const obj = value as { count: number };
  console.log(obj.count);
}

Code explanation:

  • You cannot use unknown until you narrow or assert to a concrete type
  • Safer default than any for external data

never

Functions that never return normally:

typescript
function fail(message: string): never {
  throw new Error(message);
}
 
function infiniteLoop(): never {
  while (true) {
    // ...
  }
}

never also appears when TypeScript proves a variable cannot exist (exhaustive switch checks—later).

Literal Types (Preview)

Types can be exact values, not only broad primitives:

typescript
const mode: "light" | "dark" = "light";
const port: 3000 | 8080 = 3000;

These are literal types combined with unions—very common for APIs and configuration.

Putting It Together

Code explanation:

  • Object shape uses a type alias (interfaces work similarly—next chapters)
  • tags is a string array; meta is a two-string tuple
  • Status string enum keeps allowed status values readable

Quick Reference

FAQ

Is number only integers?

No. TypeScript’s number matches JavaScript: integers and floats share one type. Use libraries or branded types if you need integers only.

Should I use Array<T> or T[]?

Either is fine. Stay consistent within a project; many style guides prefer T[] for simple arrays.

When should I use a tuple instead of an object?

Tuples suit fixed order and small arity (coordinates, [key, value]). Objects scale better when fields have names.

What is the difference between any and unknown?

any lets you do anything without checks. unknown forces you to validate or narrow before use—prefer unknown for untrusted data.

Are enums bad?

They are not “bad,” but they generate JavaScript objects. as const + union types is a modern alternative with zero enum runtime.

Does TypeScript have a char or byte type?

No built-in char/byte. Use number or Uint8Array when you need binary data.