+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Part 10 of 355

๐ŸŽจ Basic Types in TypeScript: Your Foundation for Type Safety

Master all TypeScript basic types - from primitives to arrays and enums - with practical examples and best practices ๐Ÿš€

๐ŸŒฑBeginner
25 min read

Prerequisites

  • Basic JavaScript knowledge ๐Ÿ“
  • TypeScript installed โšก
  • Understanding of variables ๐Ÿ’ป

What you'll learn

  • Master all TypeScript primitive types ๐ŸŽฏ
  • Work with arrays, tuples, and enums ๐Ÿ—๏ธ
  • Understand type inference and annotations ๐Ÿ”
  • Apply basic types in real projects โœจ

๐ŸŽฏ Introduction

Welcome to the colorful world of TypeScript types! ๐ŸŽ‰ If variables are the building blocks of your code, types are the blueprints that keep everything sturdy and safe.

Think of TypeScript types like labels on containers ๐Ÿ“ฆ. Just as you wouldnโ€™t put orange juice in a container labeled โ€œmilkโ€ (chaos!), TypeScript ensures your variables hold the right kind of data. This prevents bugs, improves code clarity, and makes your development experience delightful!

By the end of this tutorial, youโ€™ll be a TypeScript types wizard, ready to build type-safe applications! Letโ€™s explore! ๐ŸŠโ€โ™‚๏ธ

๐Ÿ“š Understanding TypeScript Types

๐Ÿค” What Are Types?

Types are like DNA for your data ๐Ÿงฌ. They define what kind of information a variable can hold and what operations you can perform on it.

JavaScript is dynamically typed (types are checked at runtime), but TypeScript adds static typing (types are checked at compile time). This means:

  • โœจ Catch errors before running your code
  • ๐Ÿš€ Get intelligent code completion
  • ๐Ÿ›ก๏ธ Refactor with confidence
  • ๐Ÿ“– Self-documenting code

๐Ÿ’ก Type Annotations vs Inference

TypeScript is smart! It can often figure out types automatically:

// ๐ŸŽฏ Type Inference - TypeScript figures it out
let message = "Hello TypeScript!"; // TypeScript knows it's a string
let count = 42;                    // TypeScript knows it's a number

// ๐Ÿ“ Type Annotations - You explicitly declare the type
let greeting: string = "Welcome!";
let age: number = 25;

// ๐Ÿ’ก When to use each?
// Use inference when it's obvious
let obvious = "I'm clearly a string!";

// Use annotations when it's not clear
let notObvious: string; // Will be assigned later
notObvious = getUserInput();

๐Ÿ”ง Primitive Types

๐Ÿ“ String Type

Strings are for text - your appโ€™s words and sentences:

// ๐ŸŽจ String basics
let firstName: string = "Sarah";
let lastName: string = 'Connor';
let fullName: string = `${firstName} ${lastName}`; // Template literals work too!

// ๐ŸŽฏ String operations
let message: string = "TypeScript is awesome!";
let shout: string = message.toUpperCase(); // "TYPESCRIPT IS AWESOME!"
let length: number = message.length;        // 22

// ๐Ÿ’ก Real-world example
function createWelcomeMessage(name: string): string {
  return `Welcome aboard, ${name}! ๐Ÿš€`;
}

// โœ… Works perfectly
console.log(createWelcomeMessage("Alex")); // "Welcome aboard, Alex! ๐Ÿš€"

// โŒ TypeScript prevents errors!
// createWelcomeMessage(123); // Error: Argument of type 'number' is not assignable

๐Ÿ”ข Number Type

Numbers handle all numeric values - integers and decimals:

// ๐ŸŽฏ Number basics
let age: number = 25;
let price: number = 19.99;
let temperature: number = -5;
let billion: number = 1_000_000_000; // Underscores for readability!

// ๐Ÿงฎ Math operations
let sum: number = 10 + 5;        // 15
let product: number = 4 * 7;     // 28
let division: number = 20 / 4;   // 5
let remainder: number = 10 % 3;  // 1

// ๐Ÿ’ฐ Real-world example: Shopping cart
function calculateTotal(items: number[], taxRate: number): number {
  const subtotal = items.reduce((sum, price) => sum + price, 0);
  const tax = subtotal * taxRate;
  return subtotal + tax;
}

const cart: number[] = [29.99, 15.50, 7.99];
const total = calculateTotal(cart, 0.08); // $57.58 with 8% tax
console.log(`Total: $${total.toFixed(2)} ๐Ÿ’ณ`);

โœ… Boolean Type

Booleans are simple but powerful - true or false:

// ๐ŸŽฏ Boolean basics
let isActive: boolean = true;
let isComplete: boolean = false;
let hasPermission: boolean = true;

// ๐Ÿ”ง Boolean logic
let canEdit: boolean = isActive && hasPermission; // true
let needsAttention: boolean = !isComplete || isActive; // true

// ๐ŸŽฎ Real-world example: Game state
interface GameState {
  isPlaying: boolean;
  isPaused: boolean;
  isGameOver: boolean;
  hasHighScore: boolean;
}

function updateGameState(state: GameState, score: number): GameState {
  return {
    ...state,
    isGameOver: score <= 0,
    hasHighScore: score > 1000,
    isPlaying: !state.isPaused && !state.isGameOver
  };
}

// ๐ŸŽฏ Usage
let gameState: GameState = {
  isPlaying: true,
  isPaused: false,
  isGameOver: false,
  hasHighScore: false
};

gameState = updateGameState(gameState, 1500);
console.log(gameState.hasHighScore ? "New high score! ๐Ÿ†" : "Keep trying! ๐Ÿ’ช");

๐Ÿ’ก Special Types

๐ŸŒŒ Null and Undefined

These represent absence of value, but theyโ€™re different:

// ๐Ÿ” Understanding null and undefined
let notYetAssigned: undefined = undefined; // Variable declared but not assigned
let explicitlyEmpty: null = null;         // Intentionally empty

// ๐Ÿ’ก Real-world usage with union types
let userEmail: string | null = null; // Email might not exist

function findUser(id: number): User | null {
  const user = database.find(u => u.id === id);
  return user || null; // Explicitly return null if not found
}

// ๐Ÿ›ก๏ธ Safe handling with strictNullChecks
function greetUser(name: string | undefined): string {
  // โŒ Unsafe - could error if name is undefined
  // return `Hello, ${name.toUpperCase()}!`;
  
  // โœ… Safe - check first!
  if (name !== undefined) {
    return `Hello, ${name.toUpperCase()}! ๐Ÿ‘‹`;
  }
  return "Hello, stranger! ๐Ÿ‘‹";
}

// ๐ŸŽฏ Optional parameters use undefined
function createProduct(name: string, description?: string): Product {
  return {
    name,
    description: description || "No description available"
  };
}

๐Ÿšซ Void Type

Void represents the absence of a return value:

// ๐ŸŽฏ Functions that don't return anything
function logMessage(message: string): void {
  console.log(`๐Ÿ“ข ${message}`);
  // No return statement!
}

// ๐ŸŽจ Event handlers often return void
function handleClick(event: MouseEvent): void {
  console.log("Button clicked! ๐Ÿ–ฑ๏ธ");
  updateUI();
  trackEvent("button_click");
  // Performs actions but doesn't return a value
}

// โš ๏ธ Void vs undefined
function returnsUndefined(): undefined {
  return undefined; // Must explicitly return undefined
}

function returnsVoid(): void {
  // Can return nothing or return; (empty return)
  return;
}

๐ŸŽญ Any Type (Use Sparingly!)

Any disables type checking - use it as a last resort:

// โš ๏ธ Any type - TypeScript gives up!
let mystery: any = 42;
mystery = "now I'm a string";
mystery = { weird: true };
mystery.nonExistent.method(); // No error at compile time! ๐Ÿ’ฅ

// ๐Ÿ›ก๏ธ Better alternatives to any
// 1. Unknown - safer any
let saferMystery: unknown = getData();
if (typeof saferMystery === 'string') {
  console.log(saferMystery.toUpperCase()); // Must check type first
}

// 2. Union types - be specific
let flexible: string | number = "hello";
flexible = 42; // Still type-safe!

// 3. Generics - maintain type safety
function processData<T>(data: T): T {
  console.log("Processing:", data);
  return data;
}

// ๐Ÿ“ When any might be acceptable (rarely!)
// Migrating JavaScript code gradually
const legacyFunction: any = window.legacyLibrary; // Third-party code

๐Ÿš€ Array and Tuple Types

๐Ÿ“š Arrays

Arrays store multiple values of the same type:

// ๐ŸŽฏ Array syntax - two ways
let numbers: number[] = [1, 2, 3, 4, 5];
let names: Array<string> = ["Alice", "Bob", "Charlie"];

// ๐ŸŽจ Working with arrays
let fruits: string[] = ["apple", "banana", "orange"];
fruits.push("mango");           // โœ… Adding strings is fine
// fruits.push(123);            // โŒ Error: can't add numbers!

// ๐Ÿ›’ Real-world example: Shopping list
interface Item {
  name: string;
  quantity: number;
  bought: boolean;
}

let shoppingList: Item[] = [
  { name: "Milk ๐Ÿฅ›", quantity: 2, bought: false },
  { name: "Bread ๐Ÿž", quantity: 1, bought: true },
  { name: "Eggs ๐Ÿฅš", quantity: 12, bought: false }
];

// ๐ŸŽฏ Array methods with types
const unboughtItems: Item[] = shoppingList.filter(item => !item.bought);
const itemNames: string[] = shoppingList.map(item => item.name);
const totalQuantity: number = shoppingList.reduce(
  (sum, item) => sum + item.quantity, 
  0
);

// ๐ŸŽฎ Multi-dimensional arrays
let gameBoard: string[][] = [
  ["X", "O", "X"],
  ["O", "X", "O"],
  ["X", "O", "X"]
];

๐ŸŽฏ Tuples

Tuples are fixed-length arrays with specific types at each position:

// ๐Ÿ“ Tuple basics - order and types matter!
let coordinate: [number, number] = [10, 20];
let user: [string, number, boolean] = ["Alice", 25, true];

// ๐ŸŽจ Named tuples (TypeScript 4.0+)
type Point3D = [x: number, y: number, z: number];
let position: Point3D = [10, 20, 30];

// ๐ŸŒˆ Real-world example: RGB colors
type RGB = [red: number, green: number, blue: number];
let primaryRed: RGB = [255, 0, 0];
let oceanBlue: RGB = [0, 119, 190];

function mixColors(color1: RGB, color2: RGB): RGB {
  return [
    Math.round((color1[0] + color2[0]) / 2),
    Math.round((color1[1] + color2[1]) / 2),
    Math.round((color1[2] + color2[2]) / 2)
  ];
}

// ๐Ÿ“Š Database query results
type QueryResult = [id: number, name: string, email: string];
let userRecord: QueryResult = [1, "John Doe", "[email protected]"];

// ๐ŸŽฏ Destructuring tuples
let [id, name, email] = userRecord;
console.log(`User ${name} (${email}) has ID: ${id}`);

// โš ๏ธ Tuples vs Arrays
let flexibleArray: number[] = [1, 2, 3, 4, 5]; // Can have any length
let strictTuple: [number, number] = [1, 2];    // Must have exactly 2 elements

๐ŸŽจ Enum Type

Enums define a set of named constants:

// ๐ŸŽฏ Numeric enums
enum Direction {
  Up,    // 0
  Down,  // 1
  Left,  // 2
  Right  // 3
}

let playerDirection: Direction = Direction.Up;

// ๐ŸŽฎ Game example with custom values
enum GameStatus {
  NotStarted = 0,
  InProgress = 1,
  Paused = 2,
  GameOver = 3,
  Victory = 4
}

function handleGameStatus(status: GameStatus): string {
  switch (status) {
    case GameStatus.NotStarted:
      return "Press START to begin! ๐ŸŽฎ";
    case GameStatus.InProgress:
      return "Game on! ๐Ÿƒโ€โ™‚๏ธ";
    case GameStatus.Paused:
      return "Paused - Press P to continue โธ๏ธ";
    case GameStatus.GameOver:
      return "Game Over! Try again? ๐Ÿ’€";
    case GameStatus.Victory:
      return "You win! Congratulations! ๐Ÿ†";
  }
}

// ๐ŸŽจ String enums
enum Color {
  Red = "#FF0000",
  Green = "#00FF00",
  Blue = "#0000FF",
  Purple = "#800080"
}

let favoriteColor: Color = Color.Purple;
console.log(`My favorite color is ${favoriteColor}`); // "#800080"

// ๐ŸŒ Real-world example: HTTP status codes
enum HttpStatus {
  OK = 200,
  Created = 201,
  BadRequest = 400,
  Unauthorized = 401,
  NotFound = 404,
  ServerError = 500
}

function handleResponse(status: HttpStatus): void {
  if (status === HttpStatus.OK) {
    console.log("Success! โœ…");
  } else if (status >= 400) {
    console.log("Error occurred! โŒ");
  }
}

// ๐ŸŽฏ Const enums (more efficient)
const enum Size {
  Small = "S",
  Medium = "M",
  Large = "L",
  ExtraLarge = "XL"
}

let shirtSize: Size = Size.Medium;

โš ๏ธ Common Pitfalls and Solutions

๐Ÿ˜ฑ Pitfall 1: Type Assertion Abuse

// โŒ Dangerous type assertion
let someValue: any = "This is a string";
let strLength: number = (someValue as string).length; // Works but risky!

// What if someValue changes?
someValue = 123;
// strLength = (someValue as string).length; // ๐Ÿ’ฅ Runtime error!

// โœ… Safe approach - Type guards
function getLength(value: unknown): number {
  if (typeof value === 'string') {
    return value.length;
  }
  if (Array.isArray(value)) {
    return value.length;
  }
  return 0;
}

๐Ÿคฏ Pitfall 2: Array Type Confusion

// โŒ Common mistake - wrong syntax
// let numbers: number = [1, 2, 3]; // Error!
// let names: [string] = ["Alice", "Bob"]; // This is a tuple with one element!

// โœ… Correct array syntax
let numbers: number[] = [1, 2, 3];
let names: string[] = ["Alice", "Bob"];

// โŒ Mixing types without union
// let mixed: string[] = ["hello", 42]; // Error!

// โœ… Use union types for mixed arrays
let mixed: (string | number)[] = ["hello", 42, "world", 100];

๐Ÿ˜ต Pitfall 3: Null/Undefined Confusion

// โŒ Not handling null/undefined
function getUser(id: number): User | null {
  return database.find(user => user.id === id) || null;
}

let user = getUser(123);
// console.log(user.name); // ๐Ÿ’ฅ Object is possibly 'null'

// โœ… Proper null checking
if (user !== null) {
  console.log(user.name); // Safe!
}

// โœ… Or use optional chaining
console.log(user?.name || "User not found");

๐Ÿ› ๏ธ Best Practices

๐ŸŽฏ Type Best Practices

  1. ๐Ÿท๏ธ Always Use Specific Types: Be as specific as possible

    // โŒ Too generic
    let data: any[] = [1, 2, 3];
    
    // โœ… Specific
    let scores: number[] = [1, 2, 3];
  2. ๐Ÿ“ Let TypeScript Infer When Obvious: Donโ€™t over-annotate

    // โŒ Redundant
    let name: string = "Alice";
    
    // โœ… Clean
    let name = "Alice"; // TypeScript knows it's a string
  3. ๐Ÿ›ก๏ธ Enable Strict Mode: Maximum type safety

    {
      "compilerOptions": {
        "strict": true,
        "strictNullChecks": true
      }
    }
  4. ๐ŸŽจ Use Enums for Fixed Sets: Better than magic strings

    // โŒ Magic strings
    if (status === "active") { }
    
    // โœ… Type-safe enum
    if (status === UserStatus.Active) { }
  5. โœจ Prefer Unknown Over Any: Safer for unknown types

    // โŒ Dangerous
    function process(data: any) { }
    
    // โœ… Safe
    function process(data: unknown) { }

๐Ÿงช Hands-On Exercise

๐ŸŽฏ Challenge: Build a Type-Safe Task Manager

Create a task management system using all the basic types:

๐Ÿ“‹ Requirements:

  • โœ… Use all primitive types (string, number, boolean)
  • ๐Ÿท๏ธ Create enums for task status and priority
  • ๐Ÿ‘ฅ Use arrays for task lists
  • ๐Ÿ“… Handle null/undefined for optional fields
  • ๐ŸŽจ Use tuples for task metadata

๐Ÿš€ Bonus Points:

  • Implement type-safe filtering
  • Add date handling
  • Create summary statistics

๐Ÿ’ก Solution

๐Ÿ” Click to see solution
// ๐ŸŽฏ Enums for task properties
enum TaskStatus {
  Todo = "TODO",
  InProgress = "IN_PROGRESS",
  Done = "DONE",
  Archived = "ARCHIVED"
}

enum TaskPriority {
  Low = 1,
  Medium = 2,
  High = 3,
  Urgent = 4
}

// ๐Ÿ“ Task interface using all basic types
interface Task {
  id: number;                    // number
  title: string;                 // string
  description: string | null;    // string or null
  isCompleted: boolean;          // boolean
  priority: TaskPriority;        // enum
  status: TaskStatus;            // enum
  tags: string[];                // array
  assignee?: string;             // optional (undefined)
  dueDate: Date | null;          // Date or null
  metadata: [created: Date, modified: Date]; // tuple
}

// ๐Ÿ—๏ธ Task Manager class
class TaskManager {
  private tasks: Task[] = [];
  private nextId: number = 1;
  
  // โž• Add new task
  addTask(
    title: string,
    priority: TaskPriority = TaskPriority.Medium
  ): Task {
    const now = new Date();
    const newTask: Task = {
      id: this.nextId++,
      title,
      description: null,
      isCompleted: false,
      priority,
      status: TaskStatus.Todo,
      tags: [],
      dueDate: null,
      metadata: [now, now]
    };
    
    this.tasks.push(newTask);
    console.log(`โœ… Task added: ${title}`);
    return newTask;
  }
  
  // ๐Ÿ” Find tasks by status
  getTasksByStatus(status: TaskStatus): Task[] {
    return this.tasks.filter(task => task.status === status);
  }
  
  // ๐Ÿ“Š Get statistics
  getStats(): Record<string, number> {
    const stats = {
      total: this.tasks.length,
      completed: 0,
      inProgress: 0,
      highPriority: 0
    };
    
    this.tasks.forEach(task => {
      if (task.isCompleted) stats.completed++;
      if (task.status === TaskStatus.InProgress) stats.inProgress++;
      if (task.priority >= TaskPriority.High) stats.highPriority++;
    });
    
    return stats;
  }
  
  // ๐ŸŽจ Update task
  updateTask(id: number, updates: Partial<Task>): void {
    const taskIndex = this.tasks.findIndex(t => t.id === id);
    if (taskIndex !== -1) {
      const task = this.tasks[taskIndex];
      this.tasks[taskIndex] = {
        ...task,
        ...updates,
        metadata: [task.metadata[0], new Date()] // Update modified date
      };
      console.log(`๐Ÿ“ Task ${id} updated`);
    }
  }
}

// ๐ŸŽฎ Usage example
const taskManager = new TaskManager();

// Add tasks
const task1 = taskManager.addTask("Learn TypeScript basics ๐Ÿ“˜", TaskPriority.High);
const task2 = taskManager.addTask("Build a project ๐Ÿ—๏ธ", TaskPriority.Medium);
const task3 = taskManager.addTask("Review and practice ๐Ÿ“š", TaskPriority.Low);

// Update task
taskManager.updateTask(task1.id, {
  status: TaskStatus.InProgress,
  description: "Master all primitive types!",
  tags: ["learning", "typescript", "fundamentals"]
});

// Get statistics
const stats = taskManager.getStats();
console.log("๐Ÿ“Š Task Statistics:", stats);

// Filter tasks
const inProgressTasks = taskManager.getTasksByStatus(TaskStatus.InProgress);
console.log(`๐Ÿ”ง Tasks in progress: ${inProgressTasks.length}`);

๐ŸŽ“ Key Takeaways

Youโ€™ve mastered TypeScript basic types! Hereโ€™s what you can now do:

  • โœ… Use all primitive types with confidence ๐Ÿ’ช
  • โœ… Work with arrays and tuples effectively ๐ŸŽฏ
  • โœ… Create and use enums for better code organization ๐Ÿท๏ธ
  • โœ… Handle null and undefined safely ๐Ÿ›ก๏ธ
  • โœ… Choose the right type for every situation! ๐Ÿš€

Remember: Types are your friends - they catch bugs, document code, and make development more enjoyable! ๐Ÿค

๐Ÿค Next Steps

Congratulations! ๐ŸŽ‰ Youโ€™ve built a solid foundation in TypeScript types!

Hereโ€™s what to do next:

  1. ๐Ÿ’ป Practice with the exercise above
  2. ๐Ÿ—๏ธ Add types to an existing JavaScript project
  3. ๐Ÿ“š Learn about interfaces and type aliases
  4. ๐ŸŒŸ Explore advanced types like unions and generics!

Remember: Every TypeScript expert started with these basics. Keep practicing! ๐Ÿš€

Happy coding! ๐ŸŽ‰๐Ÿš€โœจ