TypeScript Generics

JS
S
JavaScript

The idea is to avoid repetition of code. 1- Our function, interface or class will work with multiple data types. 2- Our function, interface or class uses that data type in several places 3- Use Generics when you need to accept multiple types as input or output.

1
2// Example 1 (Accept numtiple times and avoid any)
3function arrayAsString<T>(names: T[]): string {
4  return names.join(', ');
5}
6const result = arrayAsString(['x', 7]);
7
8// Example 2 -  Ensure that class constructor arguments are formatted correctly.
9class Report {
10  constructor(public fname: string, public lname: string) {}
11}
12function printReport<T extends Report>(report: T): void {
13  console.log(`${report.fname} ${report.lname}`);
14}
15const report = new Report('weekly', 'one');
16printReport(report);
17
18// Example 3 - Manipulating Arrays (enforce a custom type / type safety on instantiation)
19class Bookings<T> {
20  private slots: Array<T> = new Array<T>();
21  public add(slot: T): void {
22    this.slots.push(slot);
23  }
24}
25const bookingsStrings: Bookings<string> = new Bookings();
26bookingsStrings.add('2');
27bookingsStrings.add('4');
28const bookingsNumbers: Bookings<number> = new Bookings();
29bookingsNumbers.add(2);
30bookingsNumbers.add(4);
31
32// Example 4 - API Service getMethod() - use generics to accept any type and ensure that type os returned
33class APIService {
34  public getRecord<T, U>(endpoint: string, params: T[]): U {
35    const result: any = 1;
36    return result;
37  }
38  public getRecords<T, U>(endpoint: string, params: T[]): U[] {
39    const result: [any] = [1];
40    return result;
41  }
42}
43const apiService = new APIService();
44const record = apiService.getRecord<number, number>('google.com', [1, 2, 3]);
45console.log(record);
46
47
48// Example 5 - Accept multiple types (whislt ensuring type safety)
49function getCrons<T>(arg: T): T {
50  return arg;
51}
52function getCronsTuple<T, U>(arg1: T, arg2: U): [T, U] {
53  return [arg1, arg2];
54}
55const x = getCrons(1); //typeof x is number
56const y = getCronsTuple('xx', 3);
57
58// Example 6 - Access any property of an object in a safe way
59function getAnyObjectProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
60  return obj[key];
61}
62enum Difficulty {
63  Easy,
64  Intermediate,
65  Hard
66}
67let typescriptInfo = {
68  name: 'Typescript',
69  superset_of: 'Javascript',
70  difficulty: Difficulty.Intermediate
71};
72let supersetOf: Difficulty = getAnyObjectProperty(typescriptInfo, 'difficulty');
73
74// Troubleshooting
75// Will cause an error:
76function getCrons<T>(arg: T): T {
77  return arg.length;
78}
79// Fix:
80interface Length {
81  length: number;
82}
83function getCrons<T extends Length>(arg: T): T {
84  return arg.length;
85}

Created on 12/2/2019