Skip to main content

TypeScript

See also JavaScript.

Getting Started

Package Management

Package management is the same as JavaScript.

Note: You often need to install type information as a separate dependency. Use -D or --save-dev to install it as a dev dependency because it's not needed at runtime.

pnpm add lodash
pnpm add -D @types/lodash

Run File

node with manual compilation

# Install TypeScript as a dev dependency
pnpm add -D typescript

# Create a tsconfig.json file
npx tsc --init

# Manual compilation and run
npx tsc myfile.ts && node myfile.js

ts-node (No manual compilation)

pnpm add -D ts-node

# Run a TS file directly
ts-node myfile.ts

Type System

Basic Types

Type annotations use a colon just like Python

let age: number = 30;  // All numbers (integers and decimals) use 'number'
let price: number = 19.99; // No separate float/double - all are 'number'
let bigInt: bigint = 123456789012345678901234567890n; // For very large integers

let name: string = "John";
let isActive: boolean = true;

let items: string[] = ["item1", "item2"];
let tuple: [string, number] = ["id", 123]; // fixed length, defined types

let anyType: any = "anything"; // avoid `any` type when possible

Note on numeric types: Unlike languages like C, Java, or Go, TypeScript (and JavaScript) only has one numeric type: number. All numbers are stored as IEEE 754 double-precision floating-point format, so there's no distinction between integers, floats, or doubles. Use bigint for very large integers that exceed the safe integer range.

TypeScript can infer types - no need to always annotate

let inferred = "John";  // TypeScript knows this is a string
let numbers = [1, 2, 3]; // TypeScript knows this is number[]

Enums

enum Role {
User = "USER",
Admin = "ADMIN",
Guest = "GUEST"
}

let userRole: Role = Role.Admin;

Interfaces & Types

// Interface - defines shape of an object
interface User {
id: number;
name: string;
email: string;
isAdmin?: boolean; // Optional property
readonly createdAt: Date; // Can't be modified after creation
}

// Use the interface
const user: User = {
id: 1,
name: "John",
email: "john@example.com",
createdAt: new Date()
};

// Type aliases - alternative to interfaces
type Point = {
x: number;
y: number;
};

// Union types (similar to Python's Union)
type ID = string | number;
let userId: ID = "abc123";
userId = 456; // Also valid

Generics

// No need to import TypeVar

// The instance of T is created within the signature

function getFirst<T>(array: T[]): T | undefined {
return array[0];
}

const first = getFirst<string>(["a", "b", "c"]); // Type: string
const firstNum = getFirst([1, 2, 3]); // Type inferred: number

Using Types

Functions

// Parameter and return type annotations
function greet(name: string): string {
return `Hello, ${name}!`;
}

// Arrow functions
const multiply = (a: number, b: number): number => a * b;

// Optional parameters with ?
function logMessage(message: string, userId?: string): void {
// userId is optional
console.log(message, userId || 'anonymous');
}

// Default parameters
function createUser(name: string, role: string = "user"): object {
return { name, role };
}

Classes

class Person {
// Class properties with access modifiers
private id: number; // Can only be accessed within the class
public name: string; // Can be accessed anywhere
protected age: number; // Can be accessed within the class and subclasses

// Constructor
constructor(id: number, name: string, age: number) {
this.id = id;
this.name = name;
this.age = age;
}

// Methods
greet(): string {
return `Hello, I'm ${this.name}`;
}
}

// Inheritance
class Employee extends Person {
department: string; // default public

constructor(id: number, name: string, age: number, department: string) {
super(id, name, age); // Call parent constructor
this.department = department;
}
}

Web Application Specifics

DOM Manipulation

// Type assertions when working with DOM
const button = document.getElementById('submit') as HTMLButtonElement;
// Or with angle bracket syntax (not used in JSX)
const input = <HTMLInputElement>document.getElementById('username');

// Event listeners with proper types
button.addEventListener('click', (event: MouseEvent) => {
event.preventDefault();
console.log(input.value);
});

Async/Await

// Promises and async/await (similar to Python)
async function fetchUser(id: string): Promise<User> {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json() as User;
}

Error Handling

try {
const user = await fetchUser("123");
console.log(user);
} catch (error) {
// Type narrowing with instanceof
if (error instanceof Error) {
console.error(error.message);
} else {
console.error("Unknown error:", error);
}
}

TypeScript in React

// Function component with props interface
interface GreetingProps {
name: string;
count?: number;
}

function Greeting({ name, count = 0 }: GreetingProps) {
return <h1>Hello {name}, visited {count} times</h1>;
}

// Hooks with types
const [users, setUsers] = useState<User[]>([]);

TypeScript vs Python

  1. Static Typing: TypeScript checks types at compile time, not runtime
  2. Block Scope: Variables are scoped to blocks with let and const
  3. Prototypal Inheritance: Different OOP model than Python's class-based inheritance
  4. Asynchronous Code: Uses Promises/async-await (similar to Python but with different syntax)
  5. Compilation: TypeScript compiles to JavaScript