본문 바로가기
Front end/TypeScript

[TypeScript] 다형성과 제네릭

by re-hwi 2024. 10. 27.

서론

제네릭의 개념이 헷갈려서 며칠 공부를 해보고 포스팅을 한다. 제네릭이란 선언부에서 타입을 명시하지 않고 호출이 되었을 때 타입을 명시하는 어떠한 타입도 될 수 있는 기법이다. 

 

나는 제네릭이 어떠한 타입도 될 수 있다면 unknown, any와 뭐가 다를까 하는 생각이 들었는데 오늘 드디어 뭔가 깨달은 것 같다 ㅋㅋ. 앞서 말한것 처럼 제네릭은 사용 시점의 인풋에 의해서 타입이 결정된다. 따라서 함수 혹은 인터페이스와 같은 곳에서 많이 사용된다. 

 

반면에 unknown과 any는 사용 용도 자체가 다르다. 애초에 이 두가지를 비교할 수 없을 뿐더러 unknown은 어떠한 타입도 될 수 있지만 사용하기 위해서는 타입을 명시해야 한다는 부분도 다르다.

 

any도 마찬가지로 비슷한 이유로 다르지만 이걸 쓰면 TS를 쓰는 이유가 없다고 하니 되도록이면 사용하지 않아야겠다.


다형성 (polymorphism) 

객체지향의 4가지 특징 중 하나인 다형성어떤 객체의 속성이나 기능이 상황에 따라 여러 가지 형태를 가질 수 있는 성질을 말한다. 예를 들어 '이동수단'은 전진만이 있다고 가정하자. 

 

하지만 '이동수단'의 하위인 '비행기'는 '비행' 이 있을 수도 있고 '자동차'는 '후진'을 할 수도 있다. 그렇다면 이 자동차와 비행기는 '이동수단'이 아닌가? 그것도 아니다. 

 

자동차와 비행기는 '이동수단'의 '전진'을 바탕으로 자신의 기능을 추가한 것이다. 이 과정을 메서드 오버라이딩이라고 한다. 

 

이번에는 같은 다형성의 개념인 메서드 오버로딩이다. 오버로딩은 같은 함수명에 인자를 다르게 주어 다른 함수인 것 처럼 사용하는 기법이다. 예를 들어 YYYYMMDD 형식으로 인자를 받는 함수가 있다고 하자. 

 

하지만 인자로 들어오는 타입이 string, number 혹은 Date 타입 3개 중 하나가 들어온다고 가정했을 때 메서드를 하나의 타입으로 정의한다면 반드시 오류가 날 것이다. 하지만 세 타입을 메서드 오버라이딩으로 정의하면 각각의 상황에 맞는 메서드가 호출 될 것이다. 이 기법을 메서드 오버로딩이라고 한다.


제네릭

제네릭은 앞서 설명한 것처럼 호출되는 시점에서 타입이 결정되는 기법을 말한다. 

type SuperPrint = {
    (arr: number[]) : void
    (arr: boolean[]) : void
}

const superPrint:SuperPrint = (arr) => {
    arr.forEach(i => console.log(i))
}

superPrint([1,2,3,4])
superPrint([true, true])

위 코드는 SuperPrint 타입을 지정하고 해당 타입을 사용하는 superPrint 메서드이다. 이 메서드를 여러 타입에서 사용하기 위해서는 SuperPrint타입에 해당 타입을 모두 명시해 줘야 할까? 

 

이러한 문제를 해결하기 위해 사용되는 것이 바로 제네릭이다.

 

제네릭을 이용하면 superPrint()에 어떠한 타입의 배열을 넣었을 때 해당 타입을 지정한다. 예를 들어 [1, 'hi', true] 라는 배열이 superPrint의 인자로 들어간다면 superPrint()의 타입이 그제서야 정의된다는 뜻이다. 

반응형

댓글