Обобщения — это фундаментальная особенность языков со статической типизацией, позволяющая разработчикам передавать типы в качестве параметров другому типу, функции или другой структуре. Когда разработчик делает свой компонент универсальным, он дает этому компоненту возможность принимать и применять типизацию, которая передается при использовании компонента, что повышает гибкость кода, позволяет повторно использовать компоненты и устраняет дублирование.

TypeScript полностью поддерживает универсальные шаблоны как способ обеспечить безопасность типов в компонентах, которые принимают аргументы и возвращают значения, тип которых будет неопределенным, пока они не будут использованы позже в вашем коде. В этом руководстве вы попробуете универсальные шаблоны TypeScript на реальных примерах и узнаете, как они используются в функциях, типах, классах и интерфейсах. Вы также будете использовать шаблоны для создания сопоставленных типов и условных типов, что поможет вам создавать компоненты TypeScript, обладающие гибкостью для применения ко всем необходимым ситуациям в вашем коде.

1- Generic Classes and The Keyof Operator :

class KeyValuePair<K, V> {
  constructor(public key: K, public value: V) {}
}
let kvp = new KeyValuePair<string, number>("name", 10);
/*
you can also use this syntax :
  let kvp = new KeyValuePair('name', 10); 
  the compiler will refer the type of the key and value for us
*/

2- Generic Functions :

class ArrayUtils {
  static wrapInArray<T>(value: T) {
    return Array.isArray(value) ? value : [value];
  }
}
let numbers = ArrayUtils.wrapInArray(1);
let strings = ArrayUtils.wrapInArray("hello");
console.log(numbers); // [1]
console.log(strings); // ["hello"]

3- Generic Interfaces :

interface Result<T> {
  data: T | null;
  error: string | null;
}
interface User {
  userName: string;
}
interface Product {
  productName: string;
}
function fetch<T>(url: string): Result<T> {
  return {
    data: null,
    error: null,
  };
}
fetch<User>("url").data?.userName;
fetch<Product>("url").data?.productName;

4- Generic Constraints :

class Person {
  constructor(public name: string) {}
}
class Student extends Person {}
function echo<T extends Person>(arg: T): T {
  return arg;
}
echo(new Person("John"));
echo(new Student("Zineddine"));
echo(10); // Argument of type 'number' is not assignable to parameter of type 'Person'

5- Extending Generic Classes :

class Product {
  constructor(public name: string, public price: number) {}
}
class Store<T> {
  protected _objects: T[] = [];
  addObject(object: T) {
    this._objects.push(object);
  }
  find(property: keyof T, value: unknown): T[] {
    return this._objects.filter((o) => o[property] === value);
  }
}
// pass on the generic type parameter
class CompressibleStore<T> extends Store<T> {
  compress() {
    this._objects.forEach((object) => {
      console.log(object);
    });
  }
}
let compressibleStore = new CompressibleStore<Product>();
compressibleStore.addObject(new Product("Product 1", 100));
compressibleStore.compress(); // Product { name: 'Product 1', price: 100 }
// Restrictions the generic type parameter
class SearchableStore<T extends { name: string }> extends Store<T> {
  search(searchTerm: string) {
    this._objects.find((object) => {
      return object.name === searchTerm;
    });
  }
}
// Fix the generic type parameter
class ProductStore extends Store<Product> {}
let store = new Store<Product>();
store.addObject(new Product("Product 1", 100));
store.addObject(new Product("Product 2", 200));
store.find("name", "Product 1"); // [Product { name: 'Product 1', price: 100 }]
store.find("name", "Product 3"); // []
store.find("nonExistingProperty", "Product 3"); // Argument of type '"nonExistingProperty"' is not assignable to parameter of type 'keyof Product'

6- Type mapping :

interface Product {
  name: string;
  price: number;
}
type ReadOnly<T> = {
  readonly [K in keyof T]: T[K];
};
type Optional<T> = {
  [K in keyof T]?: T[K];
};
type Nullable<T> = {
  [K in keyof T]: T[K] | null;
};

Это все для этой главы!

Ссылка на Github: Основы TypeScript в одном месте