Welcome to this concise and practical guide to TypeScript Fundamentals. Whether you're transitioning from JavaScript or enhancing your React+TypeScript workflow, this article is structured to serve as a quick-reference cheatsheet.
Each section focuses on core TypeScript topics, explained with beginner-friendly yet production-relevant examples.
Variables and Values
Variable Declaration & Type Inference
TypeScript can infer the type based on the value assigned, which reduces redundancy but still offers safety.
let name = "Alice"; // inferred as string
let age: number = 25; // explicitly typed
Using inference helps keep your code clean without losing type safety.
any
& Type Casting
any
disables type checking. Use it cautiously. Type casting helps inform TypeScript of the actual type when it can't infer correctly.
let data: any = "hello";
let len = (data as string).length;
Avoid overusing any
— it defeats TypeScript’s purpose.
Functions and Return Types
Explicit return types prevent unexpected behaviors and help with readability.
function greet(user: string): string {
return `Hello, ${user}`;
}
Even if return types are inferred, it's good practice to specify them.
Objects, Arrays, and Tuples
Objects and Property Types
You can define the exact shape of an object using inline types or interfaces.
const user: { name: string; age: number } = {
name: "Alice",
age: 30,
};
Index Signatures
When object keys are dynamic, use index signatures.
interface UserMap {
[key: string]: string;
}
const users: UserMap = {
user1: "Alice",
user2: "Bob",
};
Array Types
Arrays can be typed using type[]
or Array<type>
.
let scores: number[] = [90, 85, 100];
let names: Array<string> = ["Alice", "Bob"];
Tuples and readonly
Tuples are fixed-length arrays with specific types for each element.
let pair: readonly [string, number] = ["id", 1];
Use readonly
to make tuples immutable.
Structural vs Nominal Typing
TypeScript is structurally typed. If two types have the same structure, they are considered compatible.
interface A { x: number }
interface B { x: number }
let a: A = { x: 1 };
let b: B = a; // valid
Union and Intersection Types
Union types allow multiple possible types, while intersection types combine types.
// Union
type Status = "loading" | "success" | "error";
// Intersection
type Person = { name: string } & { age: number };
Union is like "either or", Intersection is like "both at once".
Interfaces and Type Aliases
Type Alias
A type alias gives a name to any type, useful for primitives, unions, or intersections.
type ID = number | string;
Interface extends
and implements
Interfaces can extend other interfaces or be implemented by classes.
interface Base {
id: number;
}
interface User extends Base {
name: string;
}
class Customer implements User {
id = 1;
name = "John";
}
Open Interfaces
Interfaces are open-ended and can be merged automatically, useful for extending types across modules.
interface Profile {
name: string;
}
interface Profile {
age: number;
}
// Merged: { name: string, age: number }
Recursive Types
Recursive types can describe deeply nested structures like JSON trees or folders.
type NestedList = string | NestedList[];
Type Queries, Callables, and Constructables
typeof
, keyof
, in
These operators allow you to build types from values and objects.
const user = { name: "Alice", age: 30 };
type User = typeof user; // { name: string; age: number }
type Keys = keyof User; // "name" | "age"
Type Registry Pattern
Build a type-safe object structure from static data.
const registry = {
user: { name: "Alice" },
product: { title: "Book" },
};
type Registry = typeof registry;
type RegistryKeys = keyof Registry;
Callables
Functions can also be typed using interfaces.
interface Greet {
(name: string): string;
}
const greet: Greet = (name) => `Hi, ${name}`;
void
Type
Functions that don't return anything use void
.
function log(message: string): void {
console.log(message);
}
Constructables & Function Overloads
You can type constructors and function overloads.
class Animal {
constructor(public name: string) {}
}
interface Constructor {
new (name: string): Animal;
}
this
Types
You can explicitly define what this
refers to in a function.
function say(this: { name: string }) {
console.log(this.name);
}
Useful when using .call()
or binding to custom objects.
Explicit Function Return Types
Encouraged for readability and better auto-completion.
const add = (a: number, b: number): number => a + b;
Classes and Type Guards
Class Fields and Methods
TypeScript brings full support for class features with types.
class User {
constructor(public name: string, private age: number) {}
}
Access Modifiers
public
, private
, and protected
control visibility.
class Employee {
private salary: number;
constructor(public name: string, salary: number) {
this.salary = salary;
}
}
Parameter Properties & Overrides
Shorthand for initializing fields directly from constructor parameters.
class Admin extends User {
constructor(name: string, age: number, public role: string) {
super(name, age);
}
}
Type Guards
Custom checks to narrow types at runtime.
function isString(val: any): val is string {
return typeof val === "string";
}
Great for refining types in conditional logic.
Generics
Basic Generics
Generics let you create reusable, type-safe components and functions.
function identity<T>(arg: T): T {
return arg;
}
Generic Props in React
Create components that work with any data type.
interface ListProps<T> {
items: T[];
renderItem: (item: T) => JSX.Element;
}
function List<T>({ items, renderItem }: ListProps<T>) {
return <>{items.map(renderItem)}</>;
}
Wrapping Up
Congrats on covering the TypeScript fundamentals! From variable inference to generics and type guards, you now have the base needed to:
- Work confidently with React + TypeScript
- Understand type safety across your codebase
- Scale apps with maintainable interfaces and classes
What's Next?
- Dive into React with TypeScript Patterns
- Learn TypeScript with Redux / RTK Query
- Explore Advanced Utility Types (
Partial
,Pick
,Omit
,Record
) - Use TypeScript with APIs and form validation libraries like Zod/Yup
Top comments (0)