TypeScript : Generics

holymoly.jun·2021년 7월 27일
0
post-thumbnail

Generics

Generics는 객체에 타입이 정해지지 않았을 때, 여러 타입에 대응하기 위해 사용한다. "여러 타입에 대응"한 다는 것은 객체의 확장성을 높혀주며, 재사용성을 높혀준다.

1. any로 타입 대응하기

Generics 말고, 파라미터와 반환 값의 데이터 타입을 any로 대응할 수 있다. 해당 방법에 대해서 알아보자.

//파라미터 데이터 타입 : any
//반환값 : any
export const fetchData = async (params: any): Promise<any> => {
    //fetch...
};
const datas = fetchData({ url: 'http://localhost:8080/city', query: 'korea' });

위의 코드는 typescript에서 치명적인 단점을 보여준다. 우리가 typescript를 사용하는 이유는 타입을 지정하고, 반환값의 타입을 유추하기 위해서이다.
그러나 위의 코드에서 datas의 데이터 타입은 any로 나타나지면서, 우리는 fecth 후에 서버에서 받아진 데이터 타입을 유추할 수 없게 된다.




2. 함수와 class에서 generics

우리는 위와 같은 문제를 해결하기 위해 Generics를 사용한다. 사용 방법은 객체 명 옆에 <T> 를 사용하고 객체 내에서 타입을 T 값으로 명시해준다. T는 type의 약자이다. 다른 문자를 사용해도 무방하다.

함수class에서 사용하는 방법은 아래와 같다.

2.1 any로 만든 함수 generics로 만들어보기

interface dataT {
    data: {
        id: number;
        name: string;
        company: string;
    }[];
}

export const fetchData = async <T1, T2>(params: T1): Promise<T2> => {
    const res = await fetch(`${params}`);
    return res.json();
};

const data = await fetchData<string, dataT>('http://localhost:8080/search?city=seoul');

Generics로 만들어주면 아래와 같이, IDE에서 반환값의 데이터 타입을 알 수 있다.


2.2 확장성 높은 class 만들어보기

Generics가 없이, class를 만들게 되면 class마다 type에 대한 구분을 해줘야한다. 이렇게 되면 아래와 같이 반복되는 코드가 생기며, class의 재사용성이 떨어지게 된다.

class numberQueue {
    list: number[] = [];

    enqueue(item: number) {
        this.list.push(item);
    }
    dequeue() {
        return this.list.shift();
    }
}
class stringQueue {
    list: string[] = [];

    enqueue(item: string) {
        this.list.push(item);
    }
    dequeue() {
        return this.list.shift();
    }
}

const numberQ = new numberQueue();
const stringQ = new stringQueue();

numberQ.enqueue(0);
numberQ.enqueue('a'); // error!
numberQ.enqueue(1);

console.log(numberQ.dequeue()); // 0
console.log(numberQ.dequeue()); // 1

stringQ.enqueue('a');
stringQ.enqueue(1); // error!
stringQ.enqueue('b');

console.log(stringQ.dequeue()); // 'a'
console.log(stringQ.dequeue()); // 'b'

위와 같은 코드를 Generics를 사용해 반복되는 코드는 줄이고, 재사용성을 높혀보자.

class Queue<T> {
    list: T[] = [];

    enqueue(item: T) {
        this.list.push(item);
    }
    dequeue() {
        return this.list.shift();
    }
}
const numberQ = new Queue<number>();
const stringQ = new Queue<string>();



3. interface에서 generics

interface Datas<T> {
    list: T[];
}

const items: Datas<nubmer> = {
    list: [1, 2, 3],
};



4. type alias에서 generics

type Datas<T> = {
    list: T[];
};

const datas: Datas<number> = {
    list: [1, 2, 3],
};



출처

profile
Front-End Developer

0개의 댓글