TypeScript - Generics<2> 제네릭 클래스

CH_Hwang·2022년 2월 24일
0

TypeScript

목록 보기
2/12

Generic Classes

제네릭 클래스는 제네릭 인터페이스와 유사한 형태를 가지고있다.

class GenericNumber<NumType>{
  zeroValue: NumType;
  add: (x: NumType, y: NumType) => NumType;
}

let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function (x, y) {
  return x+y;
}

위 코드는 꽤 정확한 사용이지만 number타입을 써야만한다는 제약이 없다.
그렇기 때문에 아래와 같이 string을 사용 할 수 있다.

let stringNumeric = new GenericNumber<string>();
stringNumeric.zeroValue = "";
stringNumeric.add = function (x,y){
  return x+y;
}

Generic Constraints

function loggingIdentity<Type>(arg: Type): Type {
  console.log(arg.length); // Property 'length' does not exist on type 'Type'.
  return arg;
}

위 코드 같은 경우 Type이 어떤 type인지 모르기 때문에 arg.length에서 에러가 난다. 이 경우 length를 가진 interface를 사용해주면 된다.

interface Lengthwise{
  legnth: number;
}

function loggingIdentity<Type extends Lengthwise>(arg: Type): Type {
  console.log(arg.length); // Now we know it has a .length property, so no more error
  return arg;
}

위와 같이 구성하면 length라는 프로퍼티가 없는 타입은 올 수 없다.

loggingIdentity(3);
Argument of type 'number' is not assignable to parameter of type 'Lengthwise'.

using Type Parameters in Generic Constraints

다른 타입 파라미터에 의해 제약되는 타입 파라미터를 정의할 수 있다.

function getProperty<Type, key extneds keyof Type>(obj: Type, key: Key) {
  return obj[key];
}

let x { a: 1, b: 2, c: 3, d: 4 };
getProperty(x, "a");
getProperty(x, "b");
getProperty(x, "d");
getProperty(x, "e"); // Argument of type '"e"' is not assignable to parameter of type '"a" | "b" | "c" | "d"'.

using Class Types in Generics

제네릭을 사용한 타입스크립트에서 팩토리를 만들때 생성자 함수를 통해 클래스의 타입을 참조해야한다.

function create<Type>(c: { new (): Type }): Type {
  return new c();
}
class BeeKeeper {
  hasMask: boolean = true;
}
 
class ZooKeeper {
  nametag: string = "Mikle";
}
 
class Animal {
  numLegs: number = 4;
}
 
class Bee extends Animal {
  keeper: BeeKeeper = new BeeKeeper();
}
 
class Lion extends Animal {
  keeper: ZooKeeper = new ZooKeeper();
}
 
function createInstance<A extends Animal>(c: new () => A): A {
  return new c();
}
 
createInstance(Lion).keeper.nametag;
createInstance(Bee).keeper.hasMask;

0개의 댓글