설명할수 없으면 아무것도 아니다

매일 조금씩 쓰면서 뭘 했는지 기록하고 좋았던 것과 나빴던 것을 바탕으로 새 글을 수정합니다.

Frontend Develop/TypeScript

타입스크립트 generic 제약조건, 디자인패턴 - constraints, keyof, Factory pattern

효니킴 2023. 6. 18. 14:28

📝 제약조건(Constraints / keyof)

제네릭에는 원하지 않는 속성에 접근하는 것을 막기 위해 extends 키워드를 이용해 제약 조건(Constraints)을 사용할수 있다. 

 

1. Constraints: 특정 타입들로만 동작하는 Generic 함수를 만들 때 사용한다.

2. Keyof: 두 객체를 비교할 때 사용한다.

 

 Constraints

제네릭 제약조건은 존재하지 않는 속성에 접근하는 것을 막기 위해 사용한다.

키워드는 extends이며 특정 타입들로만 동작하는 제네릭 함수를 만들고 싶을 때 사용한다.

 

Generic T에 제약 조건을 설정할 때 사용한다. (문자열 or 숫자)

제약 조건을 벗어나는 타입을 선언하면 에러가 발생한다.

 

extends 키워드를 통해 string과 number에 제약 조건을 걸어둔다.

printMessage() 함수 호출 시 제네릭 타입으로 string, number 명시하면 정상 동작을 하지만, boolean 타입을 호출하면 제약 조건으로 string, number를 선언했기 때문에 에러가 발생한다.

 

 keyof

keyof키워드를 이용하면 키에 제약 조건을 걸수 있다. 아래의 경우 U타입에 들어오는 값이 T 타입의 키에 포함 되어 있지 않다면 에러가 발생하게 된다. keyof는 두 객체간의 값을 비교할 때 사용한다.

 

 

1. getProperty() 함수에 두 파라미터 T, U를 선언했다.

2 .T를 object를 갖는 제약 조건을 걸었고, U는 그 T를 갖는 제약 조건을 걸었다. <T extends object, U extends keyof T>

3. 첫번째 함수와 다르게 두번째 함수에서 오류가 발생한다.

4. 그 이유는 Generic T는 키 값이 a, b, c 만 존재하는 object이고,

5. 두번째 파라미터 U의 값인 'z'는 Generic T의 키 값 중 존재하지 않는 값이기 때문에 오류가 발생한다.

 

📝디자인 패턴(Factory Pattern with Generics)

 

factory pattern이란 객체를 생성하는 인터페이스는 미리 정의하고, 인스턴스를 만들 클래스의 결정은 서브 클래스에서 진행하는 패턴이다.

여러개의 서브 클래스를 가진 슈퍼 클래스가 있을 때 입력에 따라 하나의 서브 클래스의 인스턴스를 반환한다.

✔ Factory Pattern

1. Car 인터페이스를 구현한다.

2. Bus, Taxi 클래스는 Car 인터페이스를 implements 시킨다.

3. 실제로 객체를 생성시키는 CarFactory 클래스에 getInstance 메소드를 전역 멤버로 구현한다.

4. CarFactory.getInstance 함수를 호출할 때 생성시키고 싶은 클래스를 인수값으로 전달한다.

5. 생성시키고 싶은 타입에 따라 생성하는 클래스를 반환하게 된다.

6. CarFactory로 구현함으로써 Bus, Taxi 클래스를 직접 new 인스턴스화 하지 않고 CarFactory.getInstance() 함수만 호출함으로써 객체를 생성할수 있다. 

7. 하지만 해당 코드에서는 Car 타입이 추가할때마다  case문을 추가해야하는 단점이 있다.

8. 예를 들어 Car 타입중에 Suv를 추가한다면 다음과 같은 case문을 추가해야한다. case "Suv"

해당 문제를 해결하기 위해서 제네릭을 활용하여 팩토리 패턴을 재구성하도록 한다. 

 

 Factory Pattern with Generics

이전 코드 처럼 Car 인터페이스, CarFactory 클래스를 구현한다.

이전 코드와 다른 점은 getInstance 메소드에 Car 인터페이스 제약조건을 가지는 제네릭을 선언하였다. <T extends Car>

제네릭으로 선언 함으로 써 getInstance 메소드에 내부로직 수정 없이 Car 인터페이스를 implements한 Bus, Taxi, Suv 모든 클래스는 CarFactory.getInstance() 함수의 인수값을 호출하여 각각 객체를 생성할수 있게 되었다.