일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- 공변성
- CI/CD
- SSR
- webpack
- 호이스팅
- 인터섹션
- 타입 좁히기
- 이분 검색
- RTK Query
- React
- CORS
- autosize
- recoil
- Cypress
- tailwind
- 태그된 유니온
- Promise
- 리터럴 타입
- 반공변성
- useAppDispatch
- dfs
- app router
- TS
- map
- 결정 알고리즘
- Jest
- ESlint
- async/await
- 투포인터
- 무한 스크롤
- Today
- Total
짧은코딩
제네릭 본문
제네릭
-틀린 예시
function add(x: string | number, y: string | number): string | number {
return x + y;
}
add(1, 2); // 3
add("1", "2"); // '12'
add(1, '2') // '12'
add('1', 2) // '12'
타입을 이렇게 정하면 아래 2줄 같은 경우 때문에 에러가 난다.
-제네릭 틀린 예시
function add<T>(x: T, y: T): T {
return x + y;
}
add(1, 2); // 3
add("1", "2"); // '12'
add(true, false);
add(1, "2"); // '12'
add("1", 2); // '12'
T는 다 같은 타입이라는 의미이다. 하지만 add(true, false) 같은 경우도 성립이 돼서 이런 경우를 고쳐야 한다.
-extends
function add<T extends number | string>(x: T, y: T): T {
return x + y;
}
add(1, 2); // 3
add("1", "2"); // '12'
add(true, false);
add(1, "2"); // '12'
add("1", 2); // '12'
이렇게 extends를 사용하면 그 뒤에 써 준 타입들만 허용한다는 의미이다. 따라서 위에 2개의 add만 되고 아래 3개는 에러가 난다.
function add<T extends number, K extends string>(x: T, y: K): T {
return x + y;
}
add(1, 2); // 3
add("1", "2"); // '12'
add(true, false);
add("1", 2); // '12'
add(1, "2"); // '12'
제네릭을 2개 사용할 수도 있다. 다만 이 코드에서는 마지막 add만이 되고 위 4개는 에러가 난다.
-forEach로 예시

제네릭 덕분에 타입을 다 추론할 수 있다.
-ts가 타입 추론을 못 할 때
function add<T>(x: T, y: T): T {
return x;
}
add<number>(1, 2);
ts가 타입 추론을 못하면 이렇게 타입을 정해 줄 수 있다.
-원하는 타입 추론을 하도록 만들어 주는 법
interface Array<T> {
filter<S extends T>(
predicate: (value: T, index: number, array: T[]) => value is S,
thisArg?: any
): S[];
filter(
predicate: (value: T, index: number, array: T[]) => unknown,
thisArg?: any
): T[];
}
const filtered = ["1", 2, "3", 4, "5"].filter(
(value) => typeof value === "string"
);
이러면 filtered의 타입은 string | number이 된다. 하지만 string으로 만들어 주고 싶다.
여기서 interface의 두번째 filter부터 살펴 보면 리턴 값의 타입이 다 같은 T 라서 무조건 string | number가 될 수 밖에 없다. 하지만 첫번재 filter는 리턴 값의 타입이 다른 S라서 string으로 바꿀 수 있는 여지가 있다.
그렇기에 첫번째 filter을 활용하면 된다.
interface Array<T> {
filter<S extends T>(
predicate: (value: T, index: number, array: T[]) => value is S,
thisArg?: any
): S[];
filter(
predicate: (value: T, index: number, array: T[]) => unknown,
thisArg?: any
): T[];
}
const predicate = (value: string | number): value is string =>
typeof value === "string";
const filtered = ["1", 2, "3", 4, "5"].filter(predicate);
predicate를 interface의 첫번째 filter에서 따와서 만들어줬다. 이게 가능한 이유는 <S extends T>이며 이 의미는 string extends string | number이기 때문이다. 따라서 filtered는 string으로 추론하게 된다.
'TS > TS(with ZeroCho)' 카테고리의 다른 글
TS와 건망증 (0) | 2022.08.20 |
---|---|
리턴값, 매개변수의 대입 범위 (0) | 2022.08.20 |
타입을 만드는 법 (0) | 2022.08.20 |
TS 기본 기식(2) (0) | 2022.08.17 |
TS 기본 지식 (0) | 2022.08.11 |