티스토리 뷰

이렇게 함수가 인자로 받는 타입이 적으면 하나하나 적어 줄 수 있겠지만,

function getSize(arr : number[] | string[]) : number {
  return arr.length
}

const arr1 = [1,2,3]
const arr2 = ['1','2','3']

getSize(arr1)
getSize(arr2)

 

여러개라면 하나하나 적어주기도 힘들고 코드가 길어져 가독성이 떨어질 것이다.

function getSize(arr : number[] | string[] | boolean[] | object[]) : number {
  return arr.length
}

const arr1 = [1,2,3]
const arr2 = ['1','2','3']
const arr3 = [true, false, false]
const arr4 = [{id: 1}, {id: 2}, {id: 3}]

getSize(arr1)
getSize(arr2)
getSize(arr3)
getSize(arr4)

 

그럴때 제네릭을 사용할 수 있다.

 

제네릭

제네릭을 사용하면 클래스나 함수 인터페이스를 다양한 타입으로 재사용할 수 있다. 선언할 때는 타입이 아닌 T를 사용해 선언하고 타입은 사용할 때 정해준다.

- 사용

<>안에 T를 적어준다. 다른 단어를 써도 되지만 보편적으로 T를 많이 쓴다. 그리고 타입을 정해주는 부분에서 T의 타입을 정해주면 된다.

 

함수의 제네릭 사용

<>안에 T를 적어준다. 인자의 타입에는 T[]라고 적어준다. 이렇게만 해줘도 타입스크립트가 알아서 추론해주어 에러가 나지 않는다.

function getSize<T>(arr : T[]) : number {
  return arr.length
}

const arr1 = [1,2,3]
const arr2 = ['1','2','3']
const arr3 = [true, false, false]
const arr4 = [{id: 1}, {id: 2}, {id: 3}]

getSize(arr1)
getSize(arr2)
getSize(arr3)
getSize(arr4)

 

굳이 명시적으로 타입을 적어주고 싶다면 적어 줄 수 있다.

function getSize<T>(arr : T[]) : number {
  return arr.length
}

const arr1 = [1,2,3]
const arr2 = ['1','2','3']
const arr3 = [true, false, false]
const arr4 = [{id: 1}, {id: 2}, {id: 3}]

getSize<number>(arr1)
getSize<string>(arr2)
getSize<boolean>(arr3)
getSize<object>(arr4)

 

interface의 제네릭 사용

interface에서도 제네릭을 사용할 수 있다. interface를 선언할때 <T>를 사용해 선언하고 제네릭을 사용할 프로퍼티에 T를 준다.

그리고 interface를 상속받는 객체에서 <'T'>자리에 해당 타입을 적어주면 된다.

interface Mobile<T>{
  name : string;
  price : number;
  options : T
}

const iphoneMini : Mobile<object> = {
  name : "iphone 12 mini",
  price : 1000,
  options : {
    sale : false
  }
}

const iphoneXR : Mobile<string> = {
  name : "iphone xr",
  price : 1000,
  options : 'coupon'
}

 

제네릭의 활용

이렇게 선언하면 showName의 object의 타입이 any라서 경고를 띄운다. 

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

interface Fruit{
  name : string;
  price : number;
}

interface Book {
  price: number;
}

const person : User = {name : 'bong', age : 60};
const banana : Fruit = {name: 'banana', price : 3000}
const book : Book = {price: 12000}

// object가 any라서 경고를 띄움
function showName(object) : string {
  return object.name;
}

showName(person)
showName(banana)
showName(book)

 

이렇게 들어오는 인자의 타입이 다양할때 제네릭을 이용해서 타입을 정해줄 수 있다. 하지만 object에 book이 들어오면 name이 없기 때문에 에러가 난다.

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

interface Fruit{
  name : string;
  price : number;
}

interface Book {
  price: number;
}

const person : User = {name : 'bong', age : 60};
const banana : Fruit = {name: 'banana', price : 3000}
const book : Book = {price: 12000}

function showName<T>(object : T) : string {
  // book에 name이 없어서 에러가 뜬다.
  // Property 'name' does not exist on type 'T'.
  return object.name;
}

showName(person)
showName(banana)
showName(book)

 

그럴때 extends를 사용해서 구체화할 수 있다. name이 string인 인자만 들어올 수 있다.

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

interface Fruit{
  name : string;
  price : number;
}

interface Book {
  price: number;
}

const person : User = {name : 'bong', age : 60};
const banana : Fruit = {name: 'banana', price : 3000}
const book : Book = {price: 12000}

function showName<T extends {name : string}>(object : T) : string {
  return object.name;
}

showName(person)
showName(banana)
// name이 없어서 에러가 남
showName(book)

 

그래서 name이 있어도 string이 아니면 에러를 띄운다. 이렇게 해주면 함수를 사용할 때 에러를 잡아낼 수 있다.

interface Money{
  name : boolean;
  price : number;
}

const money : Money = {name: true, price : 3000}

function showName<T extends {name : string}>(object : T) : string {
  return object.name;
}

// money의 name이 string이 아니기때문에 에러
showName(money)
728x90
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함