Front/TypeScript

타입 제너릭

oodada 2024. 7. 18. 22:02

제너릭 (Generics)

제너릭은 타입을 파라미터로 전달하여 타입 안정성을 확보하는 방법입니다.

함수

interface Obj {
    x: number;
}
type Arr = [number, number];

function toArray(a: string, b: string): string[];
function toArray(a: number, b: number): number[];
function toArray(a: boolean, b: boolean): boolean[];
function toArray(a: Obj, b: Obj): Obj[];
function toArray(a: Arr, b: Arr): Arr[];
function toArray(a: any, b: any) {
    return [a, b];
}

console.log(
    toArray('a', 'b'),
    toArray(1, 2),
    toArray(true, false),
    toArray({ x: 1 }, { x: 2 }),
    toArray([1, 2], [3, 4]),
);

위의 오버로딩 함수를 제너릭으로 변경하면 다음과 같습니다.

interface Obj {
    x: number;
}
type Arr = [number, number];

// 제너릭 문법을 사용하여 타입을 파라미터로 전달한다.
function toArray<T, U>(a: T, b: U): [T, U] {
    return [a, b];
}

console.log(
    toArray<string, string>('a', 'b'), // 꺽쇠 괄호 안에 타입을 명시적으로 지정 // 추론 가능하여 생략 가능하다.
    toArray<number, number>(1, 2),
    toArray<boolean, boolean>(true, false),
    toArray<Obj, Obj>({ x: 1 }, { x: 2 }),
    toArray<Arr, Arr>([1, 2], [3, 4, 5]), // 오류 발생 Arr 타입에서 요소의 개수가 다르기 때문
);

클래스

class User {
    public name;
    constructor(name: string) {
        this.name = name;
    }
    getName(): string {
        return this.name;
    }
}

const user1 = new User('김가을');
console.log(user1.getName());

위 코드를 축약하면...

class User {
    constructor(public name: string) {}
    getName(): string {
        return this.name;
    }
}

(...)

위 코드를 제너릭으로 변경하면 다음과 같습니다.

// 제너릭 문법을 사용하여 타입을 파라미터로 전달한다.
class User<T> {
    constructor(public name: T) {}
    getName(): T {
        return this.name;
    }
}

// 꺽쇠 괄호 안에 타입을 명시적으로 지정
const user1 = new User<string>('김가을');
console.log(user1.getName());

인터페이스

interface User<T> {
    name: string;
    value: T;
}

const user1: User<string> = {
    name: '김가을',
    value: '귀여움',
};
const user2: User<number> = {
    name: '김겨울',
    value: 22,
};
const user3: User<boolean> = {
    name: '김봄',
    value: true,
};
const user4: User<number[]> = {
    name: '김여름',
    value: [1, 2, 3],
};

제너릭 타입 제약

interface User<T extends string | number> {
    name: string;
    value: T;
}

const user1: User<string> = {
    name: '김가을',
    value: '귀여움',
};
const user2: User<number> = {
    name: '김겨울',
    value: 22,
};

// 제약 조건을 만족하지 않으므로 아래 코드는 오류 발생
const user3: User<boolean> = {
    name: '김봄',
    value: true,
};
const user4: User<number[]> = {
    name: '김여름',
    value: [1, 2, 3],
};
티스토리 친구하기