솔미는 성장중
[TS 2주차] 제네릭이란 무엇인가! (+ 제네릭을 제한하려면..?) 본문
제네릭은 카멜레온 같은 아이라고 생각하면 된다.
받은 타입을 그대로 반환한다! 라는 컨셉
📌 기본 문법
//함수
function testGeneric<T>(text: T):T{
return text;
}
testGeneric<string>('hello world'); //hello world
//위 코드는 function testGeneric(text: string):string { } 과 동일하다.
testGeneric<number>(3); //3
//인터페이스
interface Dropdown<T>{
value: T;
selected: boolean;
}
let product: Dropdown<string>;
let stock: Dropdown<number>;
let address: Dropdown<{city:string, zipCode:string}>;
📌 언제 사용하면 좋을까?
함수의 역할과 동작은 같은데 타입을 여러 종류로 넣고 싶을 때!
타입별로 함수를 여러개 만드는 것 보다 제네릭을 쓰는게 효율적이다.
any로도 위 기능을 하도록 만들 수 있지만 자동완성 or 에러 사전 방지를 지원하지 않기 때문에 비추!
📌 나는 제한을 좀 두고 싶은데? (feat. 제네릭의 타입 제한)
extends
예제1. 제네릭 타입을 숫자로 제약하기 (위 아래 같은 의미)
//제네릭 타입
function limitType<T extends number>(test: T): T {
return test;
}
//기존 타입 설정
function limitType(test: number): number {
return test;
}
예제2. length 속성을 갖는 타입만 사용 가능하게 제약
: string, array, object만 사용 가능.
function lengthOnly<T extends { length: number }>(value: T) {
return value.length;
}
lengthOnly('hi');
lengthOnly([4,5,6,7]);
lengthOnly({name:'abc',length:100});
=> value의 타입은 number 타입인 length를 담은 객체를 확장한 형태이다.
~~ 위 예제가 이해가 안되거나 자세한 설명을 원한다면 '더보기' 참고 ~~
1. { length: number }는 객체의 형태를 나타내는 타입이다.
2. 이 객체 내부에는 length라는 속성 이름과 그에 해당하는 값의 타입인 number가 선언되어 있다.
3. 즉, "객체의 속성 중에 length라는 속성이 있으며, 그 값은 숫자(number) 타입이어야 한다"는 제약을 의미
4. 문자열, 배열은 '.length' 속성이 내장되어있다. + 위 예제에서 마지막줄엔 length 속성을 만들어주었다.
5. 문자열:
- JavaScript에서 문자열 데이터('hi'와 같은)는 내장된 String 객체의 인스턴스로 간주한다.
- 이러한 String 객체는 .length와 같은 내장된 속성과 메서드를 가지고 있다.
- 따라서 'hi'라는 문자열 데이터도 실제로 String 객체의 인스턴스이며, .length 속성을 통해 해당 문자열의 길이에 접근할 수 있다.
- TypeScript에서는 이러한 내부적인 동작을 고려하여, 문자열 데이터 역시 String 객체의 인스턴스로 취급한다.
- 따라서 { length: number }와 같은 타입을 가지는 객체로써 { length: 2 }와 같이 문자열 데이터 역시 처리할 수 있다.
- TypeScript의 타입 시스템이 내부적으로 문자열 데이터와 문자열 객체의 속성과 메서드를 감지하여 이런 호환성을 제공하는 것 ! 결국 'hi'가 문자열 데이터임에도 불구하고 TypeScript는 이를 { length: number }와 같은 타입으로 간주하여 lengthOnly 함수와의 호환성을 유지시켜준다. 이는 TypeScript의 특별한 동작 방식으로 보면 된다.
6. 배열:
배열은 객체의 일종이고, '.length'속성을 갖고 있어서 정상 작동
7. 객체:
{length: number}를 확장한 {name:string, length:number}의 형태이기 때문에 정상 작동
extends와 함께 keyof를 쓴다면?
keyof 란?
: 특정 타입의 키 값을 추출해서 유니언 타입으로 변환해준다
예시) 위 아래가 같은 의미
type User = keyof {name: string; age:number;}
type User = "name" | "age"
extends와 keyof을 함께 쓴 예시
function printKeys <T extends keyof {name:string; age:number;}>(value:T){
console.log(value);
}
//아래 예시만 오류없이 작동
printKeys('name')
printKeys('age')
'TypeScript' 카테고리의 다른 글
[TS] 타입 호환 (0) | 2023.08.31 |
---|---|
[TS] 타입 가드 (0) | 2023.08.30 |
[TS] 타입 단언 (0) | 2023.08.30 |
[TS 2주차] 타입 별칭 vs 인터페이스 : 차이점은 무엇이고, 무엇을 써야하는가! (0) | 2023.08.22 |
[TS 1주차] 타입스크립트 (3) | 2023.08.19 |