TypeScript Introduction
Type-safe JavaScript for scalable applications
What you'll learn
Understand TypeScript's role as a typed superset of JavaScript
Annotate variables, function parameters, and return types
Define custom types with interfaces and type aliases
Use union and intersection types for flexible typing
Enable strict mode and understand its benefits
Compile TypeScript and configure tsconfig.json
TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. It adds static type checking to catch errors before runtime.
Why TypeScript?
- Catch bugs at compile time, not runtime
- Better IDE support with autocomplete and refactoring
- Self-documenting code through type annotations
- Scales well for large codebases
Basic Types
// Primitive types
const name: string = "React"
const count: number = 42
const isReady: boolean = true
// Arrays
const items: string[] = ["a", "b", "c"]
const numbers: Array<number> = [1, 2, 3]
// Tuples
const pair: [string, number] = ["age", 30]
// Union types
const id: string | number = "abc123" // or 123
Interfaces and Types
// Interface (preferred for objects)
interface User {
id: string
name: string
email: string
age?: number // Optional property
}
// Type alias
type Status = "active" | "inactive" | "pending"
// Using interfaces together
interface Admin extends User {
role: "admin"
permissions: string[]
}
function greetUser(user: User): string {
return `Hello, ${user.name}!`
}
Functions
// Parameter types and return type
function add(a: number, b: number): number {
return a + b
}
// Arrow function with type
const multiply = (a: number, b: number): number => a * b
// Optional and default params
function greet(name: string, greeting = "Hello"): string {
return `${greeting}, ${name}!`
}
Generics
Generics let you write reusable, type-safe code:
// Generic function
function firstElement<T>(arr: T[]): T | undefined {
return arr[0]
}
const first = firstElement([1, 2, 3]) // type: number | undefined
// Generic interface
interface ApiResponse<T> {
data: T
status: number
error?: string
}
const userResponse: ApiResponse<User> = {
data: { id: "1", name: "Alice", email: "alice@example.com" },
status: 200,
}
Type Narrowing
function process(value: string | number): string {
if (typeof value === "string") {
return value.toUpperCase() // TypeScript knows it's string here
}
return value.toFixed(2) // TypeScript knows it's number here
}
Utility Types
interface Todo {
title: string
description: string
completed: boolean
}
// Pick — select specific properties
type TodoPreview = Pick<Todo, "title" | "completed">
// Omit — exclude specific properties
type TodoWithoutDesc = Omit<Todo, "description">
// Partial — make all properties optional
type PartialTodo = Partial<Todo>
// Record — key-value map
type PageMap = Record<string, Todo>
Best Practices
- Use
interfacefor object shapes,typefor unions and primitives - Enable
strict: truein tsconfig.json - Avoid
any— useunknownwhen the type is uncertain - Prefer type inference where the type is obvious from context
- Use generics for reusable utilities
Next Steps
- Advanced Types — Deep dive into TypeScript
- React with TypeScript — Use TS with React
Key Takeaways
TypeScript is JavaScript with type checking — it compiles to plain JS and doesn't change runtime behavior
Type annotations use colon syntax (variable: type, parameter: type, return: type)
Interfaces and type aliases define object shapes and can be extended or intersected
Strict mode enables all type-checking options and is strongly recommended for production code
The TypeScript compiler (tsc) reads tsconfig.json for compiler options and project settings