Post

What are Generics?

Introduction

In this post, I will dive deeper into generics and explore them further.

Let’s begin!


What is generics

Generics are a powerful feature in TypeScript that allows you to define reusable components that work with a variety of data types. Instead of specifying concrete data types, generics use type parameters that are defined at the time of use. They provide a way to tell functions, classes, or interfaces what type you want to use when you call it.

Why use generics?

  1. Code Reusability
  2. Type Safety
  3. Flexibility

Usage of Generic Functions

1
2
3
4
5
6
7
function identity<T>(value: T): T{
    return value;
}

//example
const result1 = identity<string>("Hello"); // result1 = "Hello"
const result2 = identity<number>(1); // result2 = 1

By adding T (a type parameter) to the identity function, it can support various types while maintaining type safety. If the input value is a string, the return value must also be a string.

1
2
3
4
5
6
7
function stringIdentity(value: string): string {
    return value;
}

function numberIdentity(value: number): number {
    return value;
}

If you don’t use generics, you would need to create two separate functions to ensure type safety, as shown above. Generics help eliminate this unnecessary repetition, which is one of their biggest advantages.

실제 nestjs 프로젝트 예제

1
2
3
export declare function PassportStrategy<T extends Type<any> = any>(Strategy: T, name?: string | undefined, callbackArity?: true | number): {
    new (...args: any[]): InstanceType<T>;
};

The code above represents the PassportStrategy generic function. When using NestJS with Passport.js, PassportStrategy is a utility that simplifies extending Passport.js authentication strategy classes.

Code Explanation

<T extends Type<any> = any>

  • Ensures the type is a class type with a constructor.
  • Defaults to any if not explicitly specified.

Strategy: T

  • Strategy is a parameter that takes an authentication strategy class.
  • Typically used with classes like JwtStrategy or LocalStrategy.

name?: string | undefined

  • name is an optional parameter that specifies the name of the authentication strategy.

callbackArity?: true | number

  • callbackArity is an optional parameter to set the number of callback arguments.
  • true uses the default value, while a number specifies the exact count.

new (...args: any[]): InstanceType<T>

  • The return value is a class constructor.
  • InstanceType: Represents the instance type created from the class T.

Usage Example (JwtStrategy, LocalStrategy)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { PassportStrategy } from '@nestjs/passport';
import { Strategy, ExtractJwt } from 'passport-jwt';
import { Injectable } from '@nestjs/common';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: 'mySecretKey',
    });
  }

  async validate(payload: any) {
    return { userId: payload.sub, username: payload.username };
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-local';
import { Injectable } from '@nestjs/common';

@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy, 'local') {
  constructor() {
    super({
      usernameField: 'email', // Override default 'username' field
      passwordField: 'password',
    });
  }

  async validate(email: string, password: string): Promise<any> {
    // Implement custom user validation logic
    const user = { email, id: 1 }; // Example user
    if (!user) {
      throw new Error('Invalid credentials');
    }
    return user;
  }
}

Conclusion

Today, I studied the reasons for using generic functions, how to use them, and some practical examples. I wrote this post to refresh my memory of what I learned in the past while studying. I hope this is helpful for you as well!

Thank you for reading, and happy blogging! 🚀

References

This post is licensed under CC BY 4.0 by the author.