728x90
제네릭을 활용하자
function swap<T, U>(a: T, b: U) {
return [b, a];
}
const [a, b] = swap("1", 2);
- 2개의 타입 변수가 필요한 위와 같은 상황에서는 타입 변수를 T, U 이렇게 2개를 사용할 수 있다.
function returnFirstValue<T>(data: T[]) {
return data[0];
}
let num = returnFirstValue([0, 1, 2]);
// number
let str = returnFirstValue([1, "hello", "mynameis"]);
// number | string
- 다양한 배열 타입을 인수로 받는 제네릭 함수를 만들어야 한다.
- 함수 매개변수 data의 타입을 T[]로 설정했기 때문에 배열이 아닌 값은 인수로 전달할 수 없다.
- 배열을 인수로 전달하면 T는 배열의 요소 타입으로 할당된다.
- 변수 num에서 함수를 호출할 때 Number[] 타입의 값을 전달했으므로 T의 타입은 Number로 추론된다.
- 변수 str에서 함수를 호출할 때 (String | Number)[] 타입의 값을 전달했으므로 T의 타입은 String | Number로 추론된다.
function returnFirstValue<T>(data: [T, ...unknown[]]) {
return data[0];
}
let str = returnFirstValue([1, "hello", "mynameis"]);
// number
- 반환값의 타입을 배열의 첫 번째 요소의 타입이 되게 하려면 튜플 타입과 rest 파라미터를 사용한다.
- 우리가 구할 것은 '배열'의 '첫 번째' 요소 타입이기 때문에, 함수 매개변수의 타입을 정의할 때 튜플 타입을 이용해 첫 번째 요소의 타입은 T, 나머지 요소의 타입은 unknown[]으로 지정해 길이도, 타입도 상관 없도록 정의한다.
- 따라서 변수 str에서 함수를 호출할 때 T는 첫 번째 요소 타입인 Number 타입이 되어 함수 반환값 타입도 Number 타입이 된다.
function getLength<T extends { length: number }>(data: T) {
return data.length;
}
getLength("123"); // ✅
getLength([1, 2, 3]); // ✅
getLength({ length: 1 }); // ✅
getLength(undefined); // ❌
getLength(null); // ❌
- 타입 변수를 제한한다는 것은 함수를 호출하고, 인수로 전달할 수 있는 값의 범위에 제한을 두는 것
- 타입 변수를 적어도 length 프로퍼티를 갖는 객체 타입으로 제한하려고 한다.
- 타입 변수를 제한할 때는 확장을 이용한다.
- T extends { length: number }로 하면, T는 { length: number } 객체 타입의 서브 타입이 된다.
- 따라서 T는 무조건 Number 타입의 프로퍼티 length를 가지고 있는 타입이 되어야 한다.
- 4, 5번의 경우 length 프로퍼티가 존재하지 않으므로 오류가 발생한다.
**출처: 한 입 크기로 잘라먹는 타입스크립트 (인프런, 이정환 강사님)
728x90
'❔ TypeScript > 💭 한 입 크기 TypeScript' 카테고리의 다른 글
[TypeScript] 제네릭 인터페이스 (0) | 2023.12.21 |
---|---|
[TypeScript] map, forEach 메서드 타입 정의하기 (0) | 2023.12.21 |
[TypeScript] 제네릭 (0) | 2023.12.21 |
[TypeScript] 인터페이스와 클래스 (0) | 2023.12.21 |
[TypeScript] 접근 제어자 (0) | 2023.12.21 |