728x90

제네릭
보기에도 이상하고 워딩도 애매서
단어만 들었을땐 거부감이 좀 든다

하지만, any를 남발하지 않으려면
제네릭은 반드시 알아야만 할것으로 생각된다.

분명 많은 개발자들이 any를 쓰는 그 순간까지
아 이거 그런거 없나..
하고 생각했을텐대
알고보면 바로 그게 제네릭이다
(나만 그랬나..?)

제네릭에대해 바로 알아보자.
제네릭을 정의 하자면 "아직은 정해지지 않았지만 쓰는 사람이 쓰는 타입에 따라 유동성있게 정해지는 타입임"을 의미한다.

일단, 제네릭 없이 각 기계장치에 엔진을 간단 붙여본다.

interface Vehicle {
  run() => void;
}

class Car implements Vehicle {
  run(runTime: number) {
    console.log('4 wheels drive...', runTime);
  }
  
  changeWheel(wheelNumber: number) {
    if (wheelNumber > 4)
      throw new Error('You have only 4 wheels...');
      
    console.log('changed whleel');
  }
}

class Airplane implements Vehicle {
  run(runTime: number) {
    console.log('2 wings drive...', runTime);
  }
  
  fixWing(wingPosition: 'left' | 'right') {
    console.log('fix..!');
  }
}

function doPreRun(vehicle: Vehicle): Vehicle {
  vehicle.run(30);
  return vehicle;
}

const genesis = new Car();
genesis.changeWheel(3); // ok

doPreRun(genesis);
genesis.changeWheel(4); // failed error

위 코드에서 보다시피
예열이 되어 반환된 인스턴스는
본인의 정체성을 잃고 interface의 구현만 갖는다.
doPreRun함수가 Vehicle 인스턴스를 리턴하기 때문이다.

이러한 상황을 피하고 보다 유동성있고 추상화하여 작성하고 싶다?
이럴때 바로 제네릭이 필요하다
제네릭을 이용해 코드를 작성해본다.

function doPreRun<T>(vehicle: T): T {
  vehicle.run(30);
  return vehicle;
}

const genesis = new Car();
genesis.changeWheel(3); // ok

doPreRun(genesis);
genesis.changeWheel(4); // ok

T라는 캐릭터를 썻는데 어려워할 필요없다.
임의의 T(Type)이라는 것이니까
다른 표현으로 V(Value), K(Key) 등이 많이 쓰인다고한다.


조금만 더 나아가보자.
지금은 T라는 타입이 너무 광번위 하여
다른 개발자가 Vehicle이 아닌 인스턴스를 넘길 위험이 존재해 보인다.

function doPreRun<T extends Vehicle>(vehicle: T): T {
  vehicle.run(30);
  return vehicle;
}

const genesis = new Car();
genesis.changeWheel(3); // ok

doPreRun(genesis);
genesis.changeWheel(4); // ok

이렇게
Vehicle을 확장(상속)하여 구현한 타입만을
허용하도록 수정할 수 있다.

제네릭을 더욱 유용하게 쓰기위해
constrains라는 것에 대해 알아볼것이다.
constrains는 제네릭에 조건을 거는것이다

const obj1 = {
  name: 'mocar',
  age: 31,
};

const obj2 = {
  hasPen: true,
  hasNote: false,
};

const obj3 = {
  cash: 3000,
  debt: 1000000,
};

const getValue<T, K extends keyof T> = (obj: T, key: K): T[K] => {
  return obj[key];
}

어떤가
알고보면 그렇게 어렵지않고
매우 유용한것이다.

728x90
반응형

'개발, 코딩 > typescript' 카테고리의 다른 글

Typescript, "people.name!" - what is meaning?  (0) 2023.06.05
optional과 undefined의 차이  (0) 2022.10.26
typescript, 타입 소개  (0) 2022.10.26