AtomLearnAtomLearn
DashboardGoalsPathAchievementsReviewSign In
TypeScriptNot Started

Basic Types

string, number, boolean, arrays, tuples, any, unknown, and never — TypeScript's type system foundation

0%
Knowledge0%
Learn & Drill
Fluency0%
Drill & Speed
Retention0%
Mastery & Review
Confidence0%
All modes
Practice
Knowledge
Fluency
Retention

Knowledge Debt detected

You can study this freely — but your score may plateau if these foundations have gaps. The Mastery badge requires them to be solid.

Explanation

TypeScript adds static types to JavaScript. You annotate variables with : Type and the compiler catches type mismatches before your code runs.

Primitive types:

typescript let name: string = 'Alice'; let age: number = 30; let active: boolean = true; TypeScript infers types from initializers — you can omit the annotation when it's obvious: typescript let name = 'Alice'; // inferred: string let age = 30; // inferred: number

Arrays and Tuples:

typescript // Arrays — two equivalent syntaxes let scores: number[] = [95, 87, 92]; let tags: Array<string> = ['typescript', 'react']; // Tuple — fixed length, each position has its own type let point: [number, number] = [10, 20]; let entry: [string, number] = ['age', 30]; // entry[0] is string, entry[1] is number — order matters

`any`, `unknown`, and `never`:

| Type | Meaning | Safe? | |---|---|---| | any | Opts out of type checking entirely | No — avoid | | unknown | Unknown type, must narrow before use | Yes | | never | Value that can never occur | — (used in exhaustive checks) |

typescript
// any — no type safety (avoid)
let x: any = 'hello';
x = 42;          // no error
x.foo.bar();     // no error, but crashes at runtime

// unknown — must check type before use
let val: unknown = fetchData();
if (typeof val === 'string') {
  console.log(val.toUpperCase()); // safe — narrowed to string
}

// never — unreachable code / exhaustive checks
function fail(msg: string): never {
  throw new Error(msg);
}

`void` — for functions that return nothing: ``typescript function log(msg: string): void { console.log(msg); // no return statement (or returns undefined) }

Examples

Type annotations and inference

TypeScript infers types from initializers — annotations are only needed when the type isn't obvious from context.

// Explicit annotations
let username: string = 'alice';
let score: number = 100;
let isAdmin: boolean = false;

// Inferred — TypeScript figures it out from the value
let greeting = 'Hello, World!'; // string
let count = 0;                  // number

// Arrays
let ids: number[] = [1, 2, 3];
let names: string[] = ['Alice', 'Bob'];

// Tuple — position matters
let coordinates: [number, number] = [51.5, -0.1];
let record: [string, number, boolean] = ['Alice', 30, true];

// Type error caught at compile time (not runtime)
// username = 42;  // Error: Type 'number' is not assignable to type 'string'

any vs unknown — why it matters

Prefer `unknown` over `any` — it forces you to narrow the type before using it, keeping type safety intact.

// any — dangerous: no checks at all
function processAny(val: any) {
  return val.toUpperCase(); // TypeScript won't complain — but crashes if val is a number
}

// unknown — safe: force the caller to check the type first
function processUnknown(val: unknown) {
  // val.toUpperCase(); // Error: Object is of type 'unknown'

  if (typeof val === 'string') {
    return val.toUpperCase(); // OK — narrowed to string
  }
  return String(val);
}

// never — used in exhaustive switch statements
type Shape = 'circle' | 'square';
function area(shape: Shape): number {
  switch (shape) {
    case 'circle': return Math.PI * 5 ** 2;
    case 'square': return 5 * 5;
    default:
      const _exhaustive: never = shape; // Error if a case is missing
      return _exhaustive;
  }
}

How well did you understand this?

Next in TypeScript

Interfaces & Type Aliases

Continue