Skip to content

TypeScript Basics

Learn TypeScript, a strongly typed programming language that builds on JavaScript.

What is TypeScript?

TypeScript is a superset of JavaScript that adds static type definitions. It helps you:

  • Catch errors early during development
  • Improve code quality with better tooling
  • Enhance maintainability of large codebases
  • Better IDE support with autocomplete and refactoring

Installation

Global Installation

bash
npm install -g typescript

Project Installation

bash
npm install -D typescript
npm install -D @types/node

Initialize TypeScript Project

bash
npx tsc --init

Basic Types

Primitive Types

typescript
// String
let name: string = "John"

// Number
let age: number = 30

// Boolean
let isActive: boolean = true

// Array
let numbers: number[] = [1, 2, 3]
let names: Array<string> = ["John", "Jane"]

// Tuple
let person: [string, number] = ["John", 30]

// Enum
enum Color {
  Red,
  Green,
  Blue
}
let color: Color = Color.Red

// Any (avoid when possible)
let value: any = 42

// Void
function logMessage(): void {
  console.log("Hello")
}

// Null and Undefined
let nullable: null = null
let undefined: undefined = undefined

Object Types

typescript
// Object type
let user: {
  name: string
  age: number
  email?: string // Optional property
} = {
  name: "John",
  age: 30
}

// Interface
interface User {
  name: string
  age: number
  email?: string
}

let user2: User = {
  name: "Jane",
  age: 25
}

// Type alias
type Point = {
  x: number
  y: number
}

let point: Point = { x: 10, y: 20 }

Functions

Function Types

typescript
// Function declaration
function add(a: number, b: number): number {
  return a + b
}

// Function expression
const multiply = (a: number, b: number): number => {
  return a * b
}

// Optional parameters
function greet(name: string, greeting?: string): string {
  return `${greeting || "Hello"}, ${name}!`
}

// Default parameters
function createUser(name: string, age: number = 18): User {
  return { name, age }
}

// Rest parameters
function sum(...numbers: number[]): number {
  return numbers.reduce((total, num) => total + num, 0)
}

Function Overloads

typescript
function combine(a: string, b: string): string
function combine(a: number, b: number): number
function combine(a: any, b: any): any {
  return a + b
}

let result1 = combine("Hello", "World") // string
let result2 = combine(1, 2) // number

Classes

Basic Class

typescript
class Animal {
  private name: string
  protected species: string
  public age: number

  constructor(name: string, species: string, age: number) {
    this.name = name
    this.species = species
    this.age = age
  }

  public makeSound(): void {
    console.log(`${this.name} makes a sound`)
  }

  protected getInfo(): string {
    return `${this.name} is a ${this.species}`
  }
}

class Dog extends Animal {
  private breed: string

  constructor(name: string, age: number, breed: string) {
    super(name, "Dog", age)
    this.breed = breed
  }

  public makeSound(): void {
    console.log(`${this.getInfo()} barks`)
  }

  public getBreed(): string {
    return this.breed
  }
}

Abstract Classes

typescript
abstract class Shape {
  abstract calculateArea(): number

  public displayArea(): void {
    console.log(`Area: ${this.calculateArea()}`)
  }
}

class Circle extends Shape {
  constructor(private radius: number) {
    super()
  }

  calculateArea(): number {
    return Math.PI * this.radius ** 2
  }
}

Interfaces

Basic Interface

typescript
interface Drivable {
  speed: number
  drive(): void
}

interface Flyable {
  altitude: number
  fly(): void
}

// Multiple inheritance
class FlyingCar implements Drivable, Flyable {
  speed: number = 0
  altitude: number = 0

  drive(): void {
    console.log("Driving on road")
  }

  fly(): void {
    console.log("Flying in air")
  }
}

Extending Interfaces

typescript
interface Animal {
  name: string
  age: number
}

interface Dog extends Animal {
  breed: string
  bark(): void
}

const myDog: Dog = {
  name: "Buddy",
  age: 3,
  breed: "Golden Retriever",
  bark() {
    console.log("Woof!")
  }
}

Generics

Generic Functions

typescript
function identity<T>(arg: T): T {
  return arg
}

let output1 = identity<string>("Hello")
let output2 = identity<number>(42)

// Generic with constraints
interface Lengthwise {
  length: number
}

function logLength<T extends Lengthwise>(arg: T): T {
  console.log(arg.length)
  return arg
}

logLength("Hello") // OK
logLength([1, 2, 3]) // OK
// logLength(42) // Error: number doesn't have length

Generic Classes

typescript
class GenericStorage<T> {
  private items: T[] = []

  add(item: T): void {
    this.items.push(item)
  }

  get(index: number): T {
    return this.items[index]
  }

  getAll(): T[] {
    return this.items
  }
}

const stringStorage = new GenericStorage<string>()
stringStorage.add("Hello")

const numberStorage = new GenericStorage<number>()
numberStorage.add(42)

Advanced Types

Union Types

typescript
type StringOrNumber = string | number

function format(value: StringOrNumber): string {
  if (typeof value === "string") {
    return value.toUpperCase()
  }
  return value.toString()
}

Intersection Types

typescript
type Person = {
  name: string
  age: number
}

type Employee = {
  employeeId: string
  department: string
}

type PersonEmployee = Person & Employee

const employee: PersonEmployee = {
  name: "John",
  age: 30,
  employeeId: "E001",
  department: "Engineering"
}

Conditional Types

typescript
type ApiResponse<T> = T extends string 
  ? { message: T } 
  : { data: T }

type StringResponse = ApiResponse<string> // { message: string }
type NumberResponse = ApiResponse<number> // { data: number }

Utility Types

typescript
interface User {
  id: number
  name: string
  email: string
  age: number
}

// Partial - makes all properties optional
type PartialUser = Partial<User>

// Pick - selects specific properties
type UserSummary = Pick<User, 'id' | 'name'>

// Omit - excludes specific properties
type CreateUser = Omit<User, 'id'>

// Required - makes all properties required
type RequiredUser = Required<PartialUser>

// Record - creates object type with specific keys and values
type UserRoles = Record<string, string>

Best Practices

1. Use Strict Mode

json
// tsconfig.json
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true
  }
}

2. Prefer Interfaces for Object Shapes

typescript
// Good
interface User {
  name: string
  age: number
}

// Use type for unions, primitives, computed types
type Status = 'loading' | 'success' | 'error'

3. Use Type Guards

typescript
function isString(value: unknown): value is string {
  return typeof value === 'string'
}

function processValue(value: unknown) {
  if (isString(value)) {
    // TypeScript knows value is string here
    console.log(value.toUpperCase())
  }
}

4. Avoid any

typescript
// Bad
function process(data: any): any {
  return data.someProperty
}

// Good
function process<T>(data: T): T {
  return data
}

Next Steps

Resources

VitePress Development Guide