제네릭 타입,클래스, 제약 조건,객체의 속성을 제약하는 방법

yonghk423·2022년 1월 15일
0

제네릭 타입

아래의 두 코드는 같은 의미이다.

function logText<T>(text: T): T {
  return text;
}

// #1
let str: <T>(text: T) => T = logText;
// #2
let str: {<T>(text: T): T} = logText;

위와 같은 변형 방식으로 제네릭 인터페이스 코드를 다음과 같이 작성할 수 있다.

interface GenericLogTextFn {
  <T>(text: T): T;
}
function logText<T>(text: T): T {
  return text;
}
let myString: GenericLogTextFn = logText; // Okay
위 코드에서 만약 인터페이스에 인자 타입을 강조하고 싶다면 아래와 같이 변경할 수 있다.

interface GenericLogTextFn<T> {
  (text: T): T;
}
function logText<T>(text: T): T {
  return text;
}
let myString: GenericLogTextFn<string> = logText;

이와 같은 방식으로 제네릭 인터페이스 뿐만 아니라 클래스도 생성할 수 있습니다. 다만, 이넘(enum)과 네임스페이스(namespace)는 제네릭으로 생성할 수 없다.

제네릭 클래스

제네릭 클래스는 앞에서 살펴본 제네릭 인터페이스와 비슷하다

class GenericMath<T> {
  pi: T;
  sum: (x: T, y: T) => T;
}
let math = new GenericMath<number>();

제네릭 클래스를 선언할 때 클래스 이름 오른쪽에 를 붙여준다. 그리고 해당 클래스로 인스턴스를 생성할 때 타입에 어떤 값이 들어갈 지 지정하면 된다.

조금 전에 살펴본 인터페이스처럼 제네릭 클래스도 클래스 안에 정의된 속성들이 정해진 타입으로 잘 동작하게 보장할 수 있다.

제네릭 제약 조건

앞에서 제네릭 타입 변수에서 살펴본 내용 말고도 제네릭 함수에 어느 정도 타입 힌트를 줄 수 있는 방법이 있다.

function logText<T>(text: T): T {
  console.log(text.length); // Error: T doesn't have .length
  return text;
}

인자의 타입에 선언한 T는 아직 어떤 타입인지 구체적으로 정의하지 않았기 때문에 length 코드에서 오류가 납니다. 이럴 때 만약 해당 타입을 정의하지 않고도 length 속성 정도는 허용하려면 아래와 같이 작성하면 된다.

interface LengthWise {
  length: number;
}

function logText<T extends LengthWise>(text: T): T {
  console.log(text.length);
  return text;
}

위와 같이 작성하게 되면 타입에 대한 강제는 아니지만 length에 대해 동작하는 인자만 넘겨받을 수 있게 됩니다.

logText(10); // Error, 숫자 타입에는 length가 존재하지 않으므로 오류 발생
logText({ length: 0, value: 'hi' }); // text.length 코드는 객체의 속성 접근과 같이 동작하므로 오류 없음

객체의 속성을 제약하는 방법

두 객체를 비교할 때도 제네릭 제약 조건을 사용할 수 있다.

function getProperty<T, O extends keyof T>(obj: T, key: O) {
  return obj[key];  
}
let obj = { a: 1, b: 2, c: 3 };

getProperty(obj, "a"); // okay
getProperty(obj, "z"); // error: "z"는 "a", "b", "c" 속성에 해당하지 않습니다.

제네릭을 선언할 때 부분에서 첫 번째 인자로 받는 객체에 없는 속성들은 접근할 수 없게끔 제한하였다.

출처
https://joshua1988.github.io/ts/intro.html

profile
기록하는 개발자

0개의 댓글