Skip to content

Core Concepts of TypeScript

1. Static Typing

  • Basic Types: number, string, boolean, array, tuple, enum, any, void, null, undefined, never, object.
  • Custom Types: Use type and interface to define custom types.
  • Type Inference: TypeScript automatically infers types but allows explicit declarations to enhance type checking.
let age: number = 30;
let name: string = "John";
let isActive: boolean = true;

2. Interfaces

  • Define the shape of an object, including properties and methods.
  • Interfaces can extend (extends) other interfaces, allowing the construction of complex types.

interface User {
  name: string;
  age: number;
  isActive: boolean;
}

const user: User = { name: "Alice", age: 25, isActive: true };

3. Type Aliases

  • Use the type keyword to create type aliases, which can define complex types such as union types, intersection types, etc.

type ID = number | string;

let userId: ID = 101;
userId = "A123";

4. Classes

  • TypeScript supports ES6 class syntax with added type support.
  • Classes can have access modifiers (public, private, protected) to control access to members.
  • Supports abstract classes (abstract class) and interface implementation (implements).

class Person {
  private name: string;

  constructor(name: string) {
    this.name = name;
  }

  greet() {
    return `Hello, ${this.name}`;
  }
}

const person = new Person("Jane");
console.log(person.greet()); // "Hello, Jane"

5. Generics

  • Generics allow the definition of functions, classes, or interfaces with placeholders for types, promoting code reusability.
  • Generics can be constrained (using extends) to limit the range of types they accept.

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

let output = identity<string>("Hello");

6. Modules and Namespaces

  • Modules: TypeScript uses ES6 module syntax (import, export) for code organization.
  • Namespaces: Used to create a namespace for global variables, functions, or classes to avoid naming conflicts.

// mathUtils.ts
export function add(x: number, y: number): number {
  return x + y;
}

// main.ts
import { add } from './mathUtils';

console.log(add(5, 3)); // 8

7. Type Assertions

  • Allow you to tell the compiler the exact type of a value using the as syntax or angle bracket syntax (<Type>), helping bypass compiler type checks.

let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;

8. Extract<T, U>

  • Description: Constructs a type by extracting from T all properties that are assignable to U. This is the opposite of Exclude.

function isString(value: any): value is string {
  return typeof value === "string";
}

function print(value: string | number) {
  if (isString(value)) {
    console.log("It's a string: " + value);
  } else {
    console.log("It's a number: " + value);
  }
}

9. Union and Intersection Types

  • Union Types: Allow a variable to be one of several types, defined using the | operator.
  • Intersection Types: Combine multiple types into one, defined using the & operator.

type SuccessResponse = { success: true, data: string };
type ErrorResponse = { success: false, error: string };

type Response = SuccessResponse | ErrorResponse;

function handleResponse(response: Response) {
  if (response.success) {
    console.log(response.data);
  } else {
    console.log(response.error);
  }
}

10. Decorators

  • Decorators are a special type of declaration that can be attached to a class declaration, method, accessor, property, or parameter, often used in meta-programming like logging or access control.

function ReadOnly(target: any, key: string) {
  Object.defineProperty(target, key, {
    writable: false
  });
}

class Book {
  @ReadOnly
  title: string = "TypeScript Handbook";
}

const book = new Book();
book.title = "New Title"; // Error: Cannot assign to 'title' because it is a read-only property.

11. Asynchronous Programming

  • Supports async/await syntax, making asynchronous code appear synchronous.
  • Combines Promise with async to handle asynchronous operations.
async function fetchData(url: string): Promise<void> {
  try {
    let response = await fetch(url);
    let data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Error:', error);
  }
}

fetchData("https://api.example.com/data");

12. Compiler Configuration (tsconfig.json)

  • Configure TypeScript compilation options through the tsconfig.json file, including target version (target), module resolution (module), strict mode (strict), path aliases (paths), etc.
{
  "compilerOptions": {
    "target": "ES6",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}


13. Strict Mode

  • TypeScript provides a strict mode (strict), which includes a series of checks and constraints to improve code robustness and safety.

function greet(name: string | null) {
  if (name === null) {
    throw new Error("Name cannot be null");
  }
  return "Hello, " + name.toUpperCase();
}

14. Utility Types

  • TypeScript includes built-in utility types like Partial, Pick, Omit, Readonly, Record, etc., for manipulating and transforming types.

14.1. Partial<T>

- **Description**: Constructs a type with all properties of `T` set to optional. This is useful when you want to create an object that has only some of the properties of a given type.

        interface Todo {
        title: string;
        description: string;
        completed: boolean;
        }

        type PartialTodo = Partial<Todo>;

        const todo: PartialTodo = {
        title: "Learn TypeScript",
        // description and completed are optional
        };

14.2. Pick<T, K>

- **Description**: Constructs a type by picking a set of properties `K` from type `T`. This is useful when you want to create a type with a subset of properties from another type.

    interface Todo {
    title: string;
    description: string;
    completed: boolean;
    }

    type TodoPreview = Pick<Todo, "title" | "completed">;

    const todo: TodoPreview = {
    title: "Learn TypeScript",
    completed: false,
    // description is not included in TodoPreview
    };

14.3. Omit<T, K>

  • Description: Constructs a type by omitting a set of properties K from type T. This is the inverse of Pick, where you remove certain properties from a type.

    interface Todo {
    title: string;
    description: string;
    completed: boolean;
    }

    type TodoPreview = Omit<Todo, "description">;

    const todo: TodoPreview = {
    title: "Learn TypeScript",
    completed: false,
    // description is omitted
    };

14.4. Readonly<T>

  • Description: Constructs a type with all properties of T set to readonly, meaning they cannot be reassigned after being set.

    interface Todo {
    title: string;
    description: string;
    }

    const todo: Readonly<Todo> = {
    title: "Learn TypeScript",
    description: "Understand the basics of TypeScript",
    };

    // todo.title

14.5. Record<K, T>

  • Description: Constructs a type with a set of properties K of type T. It is often used to define an object with a specific set of keys and a uniform type for the values.
    type Page = "home" | "about" | "contact";

    type PageInfo = Record<Page, string>;

    const nav: PageInfo = {
    home: "/home",
    about: "/about",
    contact: "/contact",
    };


14.6. Required<T>

  • Description: Constructs a type by making all properties of T required. This is the opposite of Partial.
    interface Todo {
    title?: string;
    description?: string;
    }

    type RequiredTodo = Required<Todo>;

    const todo: RequiredTodo = {
    title: "Learn TypeScript",
    description: "Understand the basics of TypeScript",
    // Now both title and description are required
    };


14.7. Exclude<T, U>

  • Description: Constructs a type by excluding from T all properties that are assignable to U. This is useful for filtering out types from a union type.

    type T = string | number | boolean;
    type NonBoolean = Exclude<T, boolean>;

    const value: NonBoolean = 42; // Allowed: string | number
    // const value: NonBoolean = true; // Error: boolean is excluded

14.8. Extract<T, U>

  • Description: Constructs a type by extracting from T all properties that are assignable to U. This is the opposite of Exclude.
    type T = string | number | boolean;
    type StringOrNumber = Extract<T, string | number>;

    const value: StringOrNumber = "hello"; // Allowed: string | number
    // const value: StringOrNumber = true; // Error: boolean is not included


14.9. NonNullable<T>

  • Description: Constructs a type by excluding null and undefined from T. This is useful when you want to remove null and undefined from a type.

    type T = string | number | null | undefined;
    type NonNullableT = NonNullable<T>;

    const value: NonNullableT = "hello"; // Allowed: string | number
    // const value: NonNullableT = null; // Error: null and undefined are excluded

14.10. ReturnType<T>

  • Description: Constructs a type consisting of the return type of function T.
    function getUser() {
    return { name: "Alice", age: 25 };
    }

    type User = ReturnType<typeof getUser>;

    const user: User = { name: "Alice", age: 25 };


15. Type Compatibility

  • TypeScript uses a structural type system, meaning type compatibility is based on the structure of the types rather than the names.

interface Person {
  name: string;
  age: number;
}

interface Employee {
  name: string;
  age: number;
  position: string;
}

let person: Person = { name: "John", age: 30 };
let employee: Employee = { name: "Alice", age: 25, position: "Developer" };

person = employee; // Allowed because `Employee` has all properties of `Person`.

---