본문 바로가기
프론트엔드/TypeScript

제네릭

by step 1 2021. 6. 22.
반응형

타입을 임의로 정해서 사용자가 함수를 사용할 때 직접 지정해줄 수 있다.

 

제네릭 함수 선언 - 동시에 여러 타입을 지정해 줄 수 있다.

function helloBasic<T, U>(message: T, commet: U): T {
  return message;
}

타입을 선언하여 사용하는 방법 - 선언한 타입과 반드시 같은 타입을 입력해주어야 한다.

// 직접 타입을 지정하는 방법
// 타입이 달라서 에러 발생
// helloBasic<string>(39);
// 정상 출력
helloBasic<string, number>("message", 1);

타입을 추론하는 방법

// 타입이 추론되어진다.
helloBasic(36, 33);

 

배열 형태로 선언하는 방법

//제네릭 함수 배열 선언
function helloArray<T>(message: T[]): T {

  // T 배열의 0번째 -> T요소 자체가 리턴된다.
  return message[0];
}

 

배열 형태로 값 지정

// Type: string
helloArray(["Hello", "World"]);

// Type: String | number
helloArray(["Hello", 5]);

 

튜플 형태로 선언

function helloTuple<T, K>(message: [T, K]): T {
  
  return message[0];
}

 

튜플 형태로 값 지정

// type: String, string
helloTuple(["Hello", "World"]);
// type: string, number
helloTuple(["Hello", 5]);

 

타입선언 방식

type HelloFunctionGeneric1 = <T>(message: T) => T; 

const helloFunction1: HelloFunctionGeneric1 = <T>(message: T): T => {
  return message;
};

 

인터페이스 선언 방식

interface HelloFunctionGeneric2 {
  <T>(message: T): T;
}

const helloFunction2: HelloFunctionGeneric2 = <T>(message: T): T => {
  return message;
};

 

class에서 제네릭을 선언하고 사용하는 방법

// class 에서 제네릭을 사용하는 방법
class Person1111<T>{
  private _name: T;

  constructor(name: T){
    this._name = name;
  }
}

new Person1111("Mark");
new Person1111<string>("aaa");

 

제네릭에 extends를 사용하는 방법

T 타입에 제한을 걸어주는 방법이다.

// 제네릭에 extends를 사용하는 방법
// T에는 string 과 number만 사용 가능하다.
class PersonExtends<T extends string | number> {
  private _nmae: T;

  constructor(name: T){
    this._nmae = name;
  }
}

new PersonExtends("Marks");
new PersonExtends(222);

// 에러 발생
// new PersonExtends(true);

 

타입을 찾는 방법

keyof 를 이용하여 key값에 해당하는 데이터만 입력이 가능하도록 설정할 수 있다.

interface IPerson {
  name: string;
  age: number;
}

// keyof를 이용하면 객체의 key값으로 타입이 정해진다.
type Keys = keyof IPerson;
const keys1: Keys = "age";
const keys2: Keys = "name";

const person555533: IPerson = {
  name: "Mark",
  age: 33
};

// IPerson[keyof IPerson] => IPerson["name" | "age"] => IPerson["name"] | IPerson["age"] => string | number
function getProp(obj: IPerson, key: keyof IPerson): IPerson[keyof IPerson] {
  return obj[key];
}

function getProp2<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}
// name 혹은 age 만 입력 가능하다.
console.log(getProp2(person555533, "age"));
console.log(getProp2(person555533, "name"));

// 유니온 타입이기 때문에 에러 발생
// function setProp(obj: IPerson, key: keyof IPerson, value: string | number): void{
//   obj[key] = value;
// }

function setProp2<T, K extends keyof T>(obj: T, key: keyof T, value: T[K]): void{
  console.log(obj);
  obj[key] = value;
}
setProp2(person555533, "name", "A");
setProp2(person555533, "age", 22);

반응형

'프론트엔드 > TypeScript' 카테고리의 다른 글

Abstract Class  (0) 2021.06.21
Class - 상속  (0) 2021.06.21
class - singleton 패턴  (0) 2021.06.21
class - Static Properties 와 Method  (0) 2021.06.21
class - index Signatures  (0) 2021.06.21