개발일지

[TS] 6. 제네릭 본문

JS, TS/[TS | 강의] TS·OOP

[TS] 6. 제네릭

lyjin 2022. 10. 30.

22.09.08 목

Function

not using genegic

  // number 타입밖에 못 받음
  function checkNotNullBad(arg: number | null): number {
    if (arg == null) {
      throw new Error('not valid number!');
    }
    return arg;
  }

  // any 타입 지양💩
  function checkNotNullAnyBad(arg: any | null): any {
    if (arg == null) {
      throw new Error('not valid number!');
    }
    return arg;
  }
  const result = checkNotNullAnyBad(123);

 

 

using genegic

  function checkNotNull<T>(arg: T | null): T {
    if (arg == null) {
      throw new Error('not valid number!');
    }
    return arg;
  }
  const num: number = checkNotNull(123);
  const boal: boolean = checkNotNull(true);

 


Class

 // either: a or b

  interface Either<L, R> {
    left: () => L;
    right: () => R;
  }

  class SimpleEither<L, R> implements Either<L, R> {
    constructor(private leftValue: L, private rightValue: R) {}

    left(): L {
      return this.leftValue;
    }

    right(): R {
      return this.rightValue;
    }
  }

  const either: Either<number, number> = new SimpleEither(4, 5);
  either.left();  // 4
  either.right(); // 5
  const best = new SimpleEither({ name: 'ellie' }, 'hello');

 


Constrains

not using genegic

  interface Employee {
    pay(): void;
  }

  class FullTimeEmployee implements Employee {
    pay(): void {
      console.log('full time !!');
    }

    workFullTime() {}
  }

  class PartTimeEmployee implements Employee {
    pay(): void {
      console.log('part time !!');
    }

    workPartTime() {}
  }

  // 세부적인 타입을 인자로 받아서 정말 추상적인 타입으로 다시 리턴하는 함수는 💩💩💩
  function pay(employee: Employee): Employee {
    employee.pay();
    return employee;
  }

  const ellie = new FullTimeEmployee();
  const bob = new PartTimeEmployee();
  ellie.workFullTime();
  bob.workPartTime();

  const ellieAfterPay = pay(ellie) as FullTimeEmployee; // as로 지정해줄 수 있긴 하지만 안쓰는 게 좋음
  const bobAfterPay = pay(bob);
  bobAfterPay.workPartTime();  // Error ⭐️

  /**
   * 1. pay(employee: Employee) Employee 이기 때문에
   * 2. ellie를 파라미터로 넘겨주면 FullTimeEmployee 타입을 잃게 됨
   * 3. pay() 밖에 사용 못함
   * >> 제네릭 쓰자 .. !!
   */

 

 

using genegic

  interface Employee {
    pay(): void;
  }

  class FullTimeEmployee implements Employee {
      ...
  }

  class PartTimeEmployee implements Employee {
    ...
  }

  // extends로 상속 받을 수 있다 ! 
  function pay<T extends Employee>(employee: T): T {
    ellie.pay();
    return employee;
  }

  const ellie = new FullTimeEmployee();
  const bob = new PartTimeEmployee();
  ellie.workFullTime();
  bob.workPartTime();

  const ellieAfterPay = pay(ellie);
  const bobAfterPay = pay(bob);

  ellieAfterPay.workPFullTime(); 
  bobAfterPay.workPartTime(); ⭐️

  /** 주의
   * 제네릭을 함수에서 쓸때는 항상 인자를 전달하는 괄호 () 앞에다가 제네릭을 정의한다. ⭐️
   **/
  const ellie2 = pay<FullTimeEmployee>(ellie);

  const pay2 = <T extends Employee>(employee: T): T => {
    ellie.pay();
    return employee;
  };

Obejct - K extends keyof T 사용해보기

const obj = {
  name: 'ellie',
  age: 20,
};

const obj2 = {
  animal: '🐕',
};

// value 타입 제한 해줄 수 있음
function getValue<T, **K extends keyof T**>(obj: T, key: K): **T[K]** {
  return obj[key];
}

console.log(getValue(obj, 'name'));    // ellie
console.log(getValue(obj, 'age'));     // 20
console.log(getValue(obj2, 'animal')); // 🐕

 

'JS, TS > [TS | 강의] TS·OOP' 카테고리의 다른 글

[TS] 9. 에러 처리 하기  (0) 2022.11.08
[TS] 7. 제네릭-Quiz  (0) 2022.10.30
[TS] 5. 객체지향 프로그래밍-Quiz  (0) 2022.10.30
[TS] 4. 객체지향 프로그래밍  (0) 2022.10.30
[TS] 3. 기본 타입-Quiz  (0) 2022.10.30