DEV Community

Cover image for 10 Must-Know TypeScript Features to Improve Your Coding Efficiency
Harish Kumar
Harish Kumar

Posted on

10 Must-Know TypeScript Features to Improve Your Coding Efficiency

TypeScript has redefined how developers write scalable and maintainable JavaScript code. While its basic features like static typing and interfaces are widely understood, there are advanced TypeScript concepts that can unlock new levels of flexibility and power in your code. Here are 10 advanced TypeScript concepts every developer should know to master this powerful superset of JavaScript.

Looking to strengthen your JavaScript foundations alongside mastering TypeScript?

Don’t miss my eBook: JavaScript: From ES2015 to ES2023. It’s the ultimate guide to modern JavaScript, covering essential features like ES modules, async/await, proxies, decorators, and much more!


1. Generics: Unlocking Reusability

Generics allow you to create components, functions, and classes that work with a variety of types while maintaining strict type safety. This concept makes your code reusable and robust.

function wrap<T>(value: T): { value: T } {
  return { value };
}

const wrappedString = wrap<string>("TypeScript"); // { value: "TypeScript" }
const wrappedNumber = wrap<number>(42); // { value: 42 }
Enter fullscreen mode Exit fullscreen mode

Generics are essential for libraries and frameworks where you need flexibility without compromising type safety.


2. Mapped Types: Transforming Object Structures

Mapped types allow you to create new types by transforming an existing type. This is particularly useful for creating readonly or optional versions of an object type.

type ReadOnly<T> = {
  readonly [K in keyof T]: T[K];
};

interface User {
  id: number;
  name: string;
}

type ReadOnlyUser = ReadOnly<User>; // { readonly id: number; readonly name: string }
Enter fullscreen mode Exit fullscreen mode

This feature is a cornerstone of type transformations in TypeScript.


3. Conditional Types: Building Dynamic Types

Conditional types enable you to create types that adapt based on a condition. They use the extends keyword to define logic.

type IsString<T> = T extends string ? "Yes" : "No";

type Test1 = IsString<string>; // "Yes"
type Test2 = IsString<number>; // "No"
Enter fullscreen mode Exit fullscreen mode

Conditional types are perfect for creating types that depend on other types, like customizing APIs or utility types.


4. Keyof and Lookup Types: Dynamically Accessing Types

The keyof operator creates a union of all property keys in an object type, while lookup types retrieve the type of a specific property dynamically.

interface User {
  id: number;
  name: string;
}

type UserKeys = keyof User; // "id" | "name"
type NameType = User["name"]; // string
Enter fullscreen mode Exit fullscreen mode

These tools are invaluable for working with dynamic objects or creating generic utility functions.


5. Utility Types: Simplifying Type Transformations

TypeScript includes built-in utility types like Partial, Pick, and Omit that simplify common type transformations.

interface User {
  id: number;
  name: string;
  email: string;
}

type PartialUser = Partial<User>; // All properties are optional
type UserIdName = Pick<User, "id" | "name">; // Only id and name
type NoEmailUser = Omit<User, "email">; // All properties except email
Enter fullscreen mode Exit fullscreen mode

These utility types save time and reduce boilerplate when modifying or adapting types.


6. Infer Keyword: Extracting Types Dynamically

The infer keyword works with conditional types to infer a type from a given context.

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

function getUser(): User {
  return { id: 1, name: "John", email: "john@example.com" };
}

type UserReturnType = ReturnType<typeof getUser>; // User
Enter fullscreen mode Exit fullscreen mode

This is commonly used in libraries to extract and manipulate types dynamically.


7. Intersection and Union Types: Combining Flexibility and Precision

Intersection types (&) and union types (|) allow you to define types that combine or differentiate multiple types.

type Admin = { role: "admin"; permissions: string[] };
type User = { id: number; name: string };

type AdminUser = Admin & User; // Must include both Admin and User properties
type AdminOrUser = Admin | User; // Can be either Admin or User
Enter fullscreen mode Exit fullscreen mode

These types are essential for modeling complex data relationships.


8. Type Guards: Refining Types at Runtime

Type guards allow you to narrow down a type dynamically during runtime. This makes working with union types safer and more predictable.

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

const value: unknown = "Hello, TypeScript";

if (isString(value)) {
  console.log(value.toUpperCase()); // Safe to call string methods
}
Enter fullscreen mode Exit fullscreen mode

By refining the type, type guards help eliminate runtime errors.


9. Template Literal Types: Creating Flexible String Types

Template literal types enable the construction of new string literal types using string templates.

type EventType = "click" | "hover" | "focus";
type EventHandler = `on${Capitalize<EventType>}`; // "onClick" | "onHover" | "onFocus"
Enter fullscreen mode Exit fullscreen mode

This feature is particularly useful for working with APIs, event handlers, and patterns that use strings in a structured way.


10. Decorators: Meta-programming for Classes and Methods

Decorators are an experimental feature in TypeScript that allow you to annotate and modify classes, properties, methods, or parameters.

function Log(target: Object, propertyKey: string) {
  console.log(`${propertyKey} was accessed`);
}

class Example {
  @Log
  sayHello() {
    console.log("Hello, world!");
  }
}
Enter fullscreen mode Exit fullscreen mode

Although decorators are still experimental, they are widely used in frameworks like Angular and NestJS for dependency injection and metadata handling.


Take Your TypeScript Skills to the Next Level

Mastering these advanced TypeScript concepts will help you write more type-safe, scalable, and maintainable code. Whether you’re working on enterprise-level applications or open-source libraries, these tools will empower you to write cleaner and more efficient TypeScript.

Want to strengthen your JavaScript skills while mastering TypeScript?

Check out my eBook: JavaScript: From ES2015 to ES2023. It’s a complete guide to modern JavaScript features, from ES6 to the latest advancements in ES2023. Understanding modern JavaScript is the perfect foundation for mastering TypeScript.

👉 Download eBook - JavaScript: from ES2015 to ES2023

javascript-from-es2015-to-es2023

Top comments (0)