Skip to content

Primitive Types

TypeScript builds on JavaScript’s primitive values, but adds static type checking that helps you catch mistakes before your code runs. Understanding how TypeScript models these primitives is the foundation for everything else in the type system.


The Core Primitive Types

string

Represents textual data.

let username: string = "Alice"

TypeScript ensures you don’t accidentally assign non‑string values:

username = 42   // ❌ Error

number

Represents all numeric values (integers, floats, NaN, Infinity).

let price: number = 19.99

TypeScript prevents accidental string concatenation:

price = "19.99" // ❌ Error

boolean

Represents true or false.

let isLoggedIn: boolean = false

null and undefined

These represent the absence of a value.

  • undefined → a variable that has been declared but not assigned
  • null → an explicit “no value” marker

In TypeScript’s strict mode, they are not assignable to other types:

let count: number = null      // ❌ Error (in strict mode)
let name: string = undefined  // ❌ Error

This prevents a huge class of runtime crashes.

If you want to allow them, you must explicitly include them:

let maybeName: string | null = null

The “Escape Hatches”: any and unknown

JavaScript developers often reach for any because it feels familiar. But TypeScript gives you two very different tools for handling unknown values.


any — Opt Out of Type Safety

any disables type checking entirely.

let data: any = fetchData()
data.toUpperCase() // ✔ Allowed, even if data is not a string

Using any is basically telling TypeScript:

“Trust me, I know what I’m doing.”

This is dangerous because it reintroduces the exact runtime bugs TypeScript is designed to prevent.

Use any only when:

  • migrating legacy JavaScript
  • dealing with extremely dynamic data
  • you need a temporary escape hatch

unknown — The Safe Alternative

unknown means “this value could be anything,” but TypeScript forces you to check before using it.

let value: unknown = getValue()

value.toUpperCase()
// ❌ Error: Object is of type 'unknown'

You must narrow the type first:

if (typeof value === "string") {
  value.toUpperCase() // ✔ Safe
}

This makes unknown the correct choice for:

  • external data (API responses, user input)
  • values you truly don’t know yet
  • safer gradual typing

When to Use unknown vs any

Scenario Use unknown Use any
You want maximum safety
You want to force type checks
You’re handling external/unsafe data
You’re migrating legacy JS
You need a temporary workaround
You want to disable type checking

Rule of thumb

Use unknown unless you have a very specific reason to use any.

unknown preserves TypeScript’s guarantees.

any removes them.


Summary

In this lesson, you learned how TypeScript models JavaScript’s primitive values:

Core primitives

  • string, number, boolean
  • null, undefined (strictly controlled)

Special types

  • any → disables type checking
  • unknown → requires type narrowing

Key takeaway

unknown is the safe, modern alternative to any.

Use any sparingly and intentionally.