TS Fundamentals
Targeting TypeScript 5.x
Syntax
Primitives
let name: string = 'Tammy'
let age: number = 28
let active: boolean = true
let nothing: null = null
let missing: undefined = undefinedArrays & Tuples
let ids: number[] = [1, 2, 3]
let names: Array<string> = ['a', 'b']
// tuple — fixed length, typed positions
let pair: [string, number] = ['age', 28]Objects
// inline
let user: { name: string; age: number } = {
name: 'Tammy',
age: 28,
}
// optional property
let config: { debug?: boolean } = {}Interfaces
interface User {
id: number
name: string
email?: string // optional
}
const user: User = { id: 1, name: 'Tammy' }Type Aliases
type ID = string | number
type Status = 'loading' | 'error' | 'success'
type Point = { x: number; y: number }
let userId: ID = 42
let state: Status = 'loading'Functions
function add(a: number, b: number): number {
return a + b
}
const greet = (name: string): string => {
return `Hello ${name}`
}
function log(msg: string, level?: string) {}Enums
enum Status {
Idle, // 0
Loading, // 1
Success, // 2
Error, // 3
}
// string enum — more readable in logs
enum Dir {
Up = 'UP',
Down = 'DOWN',
}Unknown vs Any
// any — disables type checking (avoid)
let a: any = 'hello'
a.foo.bar // no error, but unsafe
// unknown — must narrow before using
let b: unknown = 'hello'
if (typeof b === 'string') {
b.toUpperCase() // safe after check
}Void & Never
// void — function returns nothing
function log(msg: string): void {
console.log(msg)
}
// never — function never returns
function fail(msg: string): never {
throw new Error(msg)
}
function loop(): never {
while (true) {}
}Readonly & Readonly Arrays
interface User {
readonly id: number
name: string
}
const u: User = { id: 1, name: 'Tammy' }
u.id = 2 // Error: readonly
const nums: readonly number[] = [1, 2, 3]
nums.push(4) // Error: readonly
// also: ReadonlyArray<number>Index Signatures
// when keys are dynamic
interface StringMap {
[key: string]: number
}
const scores: StringMap = {
math: 95,
english: 87,
}
scores.science = 91 // validBeginner Patterns
Union Types
let id: string | number = 'abc'
id = 42 // also valid
function show(val: string | number) {
if (typeof val === 'string') {
val.toUpperCase() // TS knows it's string
}
}Intersection Types
type HasName = { name: string }
type HasAge = { age: number }
// combine — must have ALL properties
type Person = HasName & HasAge
const p: Person = { name: 'Tammy', age: 28 }Type Narrowing
function handle(val: string | number) {
if (typeof val === 'string') {
val.toUpperCase() // string methods
} else {
val.toFixed(2) // number methods
}
}
function greet(name?: string) {
if (name) {
name.toUpperCase() // definitely string
}
}Type Assertion
// tell TS you know the type
const input = document.getElementById('name') as HTMLInputElement
input.value // no error
// non-null assertion (careful)
const el = document.querySelector('.btn')!Typeof / Keyof
const config = { debug: true, port: 3500 }
// typeof — extract type from a value
type Config = typeof config
// { debug: boolean; port: number }
// keyof — union of keys
type ConfigKey = keyof Config
// 'debug' | 'port'Optional & Nullish Types
type User = {
name: string
bio?: string // string | undefined
age: number | null // explicit null
profile?: { avatar: string }
}
const user: User = { name: 'Tammy', age: 28 }
// optional chaining
const avatar = user.profile?.avatar
// nullish coalescing — fallback for null/undefined
const bio = user.bio ?? 'No bio yet'
// optional params
function greet(name?: string) {
return `Hi ${name ?? 'stranger'}`
}Intermediate Patterns
Interface Inheritance
interface Animal {
name: string
}
interface Dog extends Animal {
breed: string
}
// multiple extends — combine unrelated interfaces
interface Trainable {
level: number
}
interface ServiceDog extends Dog, Trainable {
handler: string
}
const dog: Dog = { name: 'Rex', breed: 'Lab' }Type vs Interface
// interface — extendable, declaration merges
interface User {
name: string
}
interface User {
age: number
}
// User has both name and age
// type — unions, intersections, mapped
type Result = 'ok' | 'error'
type Pair<T> = [T, T]
// rule of thumb:
// interface for object shapes
// type for everything elseLast updated on