[TypeScript] Generic 이해하기

gu·2023년 8월 17일

TypeScript

목록 보기
6/13
post-thumbnail

💻 Generic 함수

우리는 함수를 만들때 (괄호)안에 파라미터를 입력한다. 타입스크립트에서도 마찬가지로 파라미터로 타입을 입력할 수 있다. 타입을 파라미터에 넣을때 <꺽새>에 집어넘어야한다. (타입파라미터문법)

🖤 Generic 이란?

클래스 또는 함수에서 사용할 타입(type)을, 그 클래스나 함수를 사용할 때 결정하는 프로그래밍 기법을 말한다. JavaScript와 같은 동적 타입 언어만 주로 다루던 개발자에게는 생소한 개념이지만 TypeScript는 정적 타입 언어이므로 재네릭을 지원한다.

🖤 어떤 상황에서 사용할까?

TypeScript로 구현한 클래스는 일반적으로 특정 데이터 타입을 규정하지 않고, 어떤 타입이든 아이템으로 추가하거나, 추출할 수 있다. 하지만 특정 데이터 타입을 규정한 클래스를 사용하고싶을때 클래스 상속을 이용한 새로운 클래스를 생성할 수도 있다. 하지만 이런 방법은 별도의 자료타입을 받고자 하는 클래스를 추가해야 하고 중복되는 코드를 양산하기에 불편하다. 이런 경우에 재네릭을 사용할 수 있다.

  • 사용예시
function 함수(x:unknown[]){
	return x[0];
}
let a = 함수([2,4])
console.log(a) // output : 2

이 코드에서 a의 타입을 확인해보면 number타입이 아닌 unknown타입이다. array의 타입도 unknown타입이다. 타입스크립트는 숫자가 리턴되더라도 숫자 타입이라고 타입을 알아서 변경해주지 않는다. 그러므로 함수에 불확실한 unknown, any, union 타입을 입력하면 나오는 값도 unknown, any, union타입으로, 여기서 발생하는 문제들이 많다. 이럴때 타입을 파라미터로 함수에 미리 입력하는 방법도 있다. 그럼 원하는 곳에 가변적으로 타입지정이 가능하며 이것을 재네릭이라고 부른다.

🖤 재너릭 사용

function 함수<MyType>(x: MyType[]) :MyType {
  return x[0];
}


let a = 함수<number>([2,4])
let b = 함수<string>(['kim', 'park'])

// 꼭 <>를안넣더라도 기본타입을 유추해서집어넣기도한다. 결과는 같음
let a = 함수([4,2])
let b = 함수(['kim', 'park'])

이제 함수<number>() 쓰는 순간 MyType이라는 변수에 number가 들어간다고 보면된다. 그럼 이제 함수(x:number[]):number{}랑 똑같이 동작한다.
❗ 그렇다면 unknown 가득한 예시와는 다르게 return이 되는 타입이 number다.

✔ 이렇게 예시코드에서도 알 수 있듯이 Generic을 쓰면 우리가 정한 타입을 return값으로 뱉는 함수를 만들수있다.

  • 타입파라미터는 자유작명가능하다. <T>보통 이걸많이한다.
  • 일반 함수파라미터 처럼 2개 이상을 넣기도 가능하다.

🖤 Generic 타입 제한하기

✔ extends 문법

interface문법에 쓰는 (타입복사)extends와는 다른 느낌이다. Generic에서 extends는 파라미터로들어오는 속성과 비슷한 속성을 가지고 있는지 if문으로 체크하는 문법이라보면 된다.

  • 예시 #1
function 함수<MyType extends number>(x: MyType) {
  return x - 1
}

let a = 함수<number>(100) //return타입지정을 안한 이유:number-number을 했으니 알아서 number타입이 된다. 
  • 예시 #2
interface lengthCheck{
  length:number
}

  // T에 length속성을 복사해서 가진다. 
function StringCheck<T extends lengthCheck>(x:T){
  // T는 length가 있기때문에 T를 부여받은 X는 .length조작이 가능
  return console.log(x.length)
}

let str = StringCheck<string>('hello') // output: 5
// Type 'number' does not satisfy the constraint 'lengthCheck' 에러 남
let num = StringCheck<number>(123) // output: undefined
let arr = StringCheck<string[]>(['gyu','ri','Kim']) // output: 3
  • 예시 #3
function StringCheck<T extends string | string[]>(x:T){
  return console.log(x.length)
}

let str = StringCheck<string>('hello') // output: 5
let arr = StringCheck<string[]>(['gyu','ri','Kim']) // output: 3
  • 예시 #4
interface Animal {
  name: string;
  age: number;
}

let data = '{"name" : "dog", "age" : 1 }';

function 변환<T>(x: string): T {
  let con = JSON.parse(x);
  return con;
}
let ddd = 변환<Animal>(data);
console.log(ddd) // {name: "dog", age: 1}

data라는 JSON자료를 object{}자료로 변환해서 return해주는 함수를 만들었다.
-JSON.parse(): 주어진 JSON문자열을 자바스크립트 객체로 변환하는 함수다. 이 함수는 파싱된 객체를 반환한다.

0개의 댓글