티스토리 뷰
//타입 좁히기(타입 가드)
{
function numOnStr(a: number | string) {
// if (typeof a === "string") {
// a.split(",");
// } else {
// a.toFixed(1);
// }
a.toFixed(1); // number면 쓸 수 있지만 string일수도 있기 때문에 Error
}
numOnStr("123");
numOnStr(1);
}
-> 매개변수 타입이 number라면 toFixed 메서드를 사용할 수 있지만 string일수도 있기 때문에 내부에서 바로 쓰게되면 빨간 줄로 에러가 뜬다.
TS에러 메세지가 여러 줄이 뜰 때에는 결국에는 마지막 줄을 보면 된다. 마지막 줄에 원인이나 해결방법이 나와있다.
위에 a.toFixed를 사용하기 위해서는 a가 숫자라는 것을 ts에 알려줘야 하는데 첫 번째 방법으로는
강제 형변환(as)이 있다. 하지만 이 방법은 실수할 수도 있기 때문에(ts에서 에러가 안난다고해서 js로 변환했을 때 에러가 안난다고 보장할 수 없다.)
(a as number).toFixed(1);
💥결론적으로 타입이 unknwon일 때 빼고는 as로 강제형변환하는 것은 지양해야 한다.
혹은, 남이 만든 type이 틀렸을 때 -> 이때는 어쩔 수 없이 강제형변환하여 사용해야 하기 때문
as를 사용하지 않고 if문을 사용하여 타입별로 분기처리 한 뒤, 코드를 작성하는 '타입 가드'가 좋은 대안이 될 수 있다.
TS는 else문까지도 파악을 할 수 있다. if문을 통한 타입 가드는 '원시값'들을 분기처리할 때 유용하다.
타입을 지정하지 않은 매개변수가 할당문에 쓰일 경우, 예시로 위에서는 number과 string만 있는데 boolean타입이 쓰인다면 이 타입은 never로 지정되어 사용할 수 없게 된다(자동으로 타입 추론).
원시값이 아닌 배열은 어떻게 처리할까?
- Array.isArray(확인하고자하는 배열)
- 매개변수 타입이 | ("또는" 타입, union)인 경우는 많이 나오겠지만 &("그리고" 타입, intersetion)은 잘 안나옴
function numOnNumArr(a: number | number[]) {
//a가 배열임을 확인하려면 Array.isArray() 메서드를 사용하면 된다.
if (Array.isArray(a)) {
a.concat(4);
} else {
a.toFixed(3);
}
}
결론: |유니언 타입에서 분기처리는 원시값의 경우 typeof로 검사하여 분기처리하고 배열의 경우는 Array.isArray() 로 확인하여 분기처리 한다.
클래스 타입 좁히기
- 클래스는 그 자체로 타입이 될 수 있다. (당연히 대문자 시작)
- 주의점: 매개변수로 들어간 A,B 는 클래스 자체를 가리키는 것이 아니라 new키워드로 생성된 A클래스의 인스턴스와 B인스턴스를 가리킨다. -> 인자로 넘겨줄 때에도 new A() 이런 식으로 넘겨줘야 한다.
- 인스턴스 타입핑은 클래스명으로 한다. (e.g 파라미터 instanceof 클래스명)
{
//클래스는 그 자체로 타입이 될 수 있다.
class A {
aaa() {}
}
class B {
aaa() {}
}
//주의: 매개변수로 들어간 A, B는 클래스 자체를 가리키는 것은 아니고 new 키워드를 통해 생성된
// A인스턴스, B인스턴스를 말한다. -> 인스턴스 타입핑은 클래스명으로 한다.
//클래스 분기처리는 instanceof 로 클래스 검사를 해서 분기처리한다.
function aOrB(param: A | B) {
if (param instanceof A) {
param.aaa();
} else {
param.aaa();
}
}
//aOrB(A);
// aOrB(new A()); //그래서 위처럼 넘겨주는 것이 아니라 아래처럼 넘겨줘야 한다.
}
참조형에서 배열은 Array.isArray() 로 타입 체킹이 됐다. 그렇다면 객체는 어떻게 할까?
객체 타입 좁히기
- 별도의 객체를 구분하는 내장 메서드가 없기 때문에 객체가 가지고 있는 프로퍼티로 구분해줘야 한다.
- 크게 2가지 경우 1) 프로퍼티 값 2) 프로퍼티 명
- 값으로 구분할 때에는 아래의 예시처럼 타입 분기를 해주면 된다.
//객체 타입 구분-> 배열과 다르게 isArray() 같은게 없음
// 프로퍼티로 구분을 해줘야 한다. -> 경우는 크게 2가지
//1) 프로퍼티의 값이 다른 경우 2) 프로퍼티명 자체가 다른 경우
type B = { type: "b"; bbb: string };
type C = { type: "c"; ccc: string };
type D = { type: "d"; ddd: string };
//값으로 구분할 때
function typeCheck(a: B | C | D) {
if (a.type === "b") {
a.bbb;
} else if (a.type === "c") {
a.ccc;
} else {
a.ddd;
}
}
- 프로퍼티명(속성명)으로 분기할 경우 in 연산자를 사용한다.
function typeCheck(a: B | C | D) {
//a객체 안에 bbb라는 속성이 있을 경우
if ("bbb" in a) {
a.bbb;
//a객체 안에 ccc라는 속성이 있을 경우
} else if ("ccc" in a) {
a.ccc;
} else {
a.ddd;
}
}
💥보통은 type이라는 프로퍼티 값으로 많이 구분하기 때문에 타입을 만들거나 객체를 만들 때 type 이라는 프로퍼티를 추가하여 차후에 분기할 때 편하도록 추가해두는 것을 습관화하면 좋다.
커스텀 타입 가드(js, 형식 조건자)
- 위에서는 js문법인 instanceof / typeof / in / Array.isArray() 를 사용해서 타입 가드를 했지만 아래와 같이 커스텀 타입 가드 함수를 따로 만들어 사용할 수 있다. 이때 커스텀 함수의 리턴 타입에 is 를 같이 쓴다.
- is 가 없으면 if문 안에 들어갔을 때 타입을 구분할 수 없기때문에 꼭 같이 써줘야 한다.
- 타입 가드인지 아닌 지 구별방법은 리턴 타입에 is가 있으면 타입 가드 함수이다.
- is 가 아니면 제대로 타입 추론이 안되는 경우도 있기 때문에 이 개념에 대해서는 잘 알아야 한다.
//타입을 구분해주는 커스텀 함수를 직접 만들 수 있다.
interface Cat {
meow: number;
}
interface Dog {
bow: number;
}
function catOrDog(a: Cat | Dog): a is Dog {
//타입 판별을 직접 만든다.
//return 타입에 is 가 들어가 있는 애들은 커스텀 타입 가드 함수이다.
//이 함수는 if문 안의 조건문에 사용된다. 대신에 타입 판별하는 코드는 직접 작성해야 한다.
if ((a as Cat).meow) {
return false;
}
return true;
}
function pet(a: Cat | Dog) {
if (catOrDog(a)) {
console.log(a.bow);
}
if ("meow" in a) {
console.log(a.meow);
}
}
https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
'Frontend > TypeScript' 카테고리의 다른 글
[TypeScript] <제네릭> , 'is' and 'as' (0) | 2022.12.27 |
---|---|
[TypeScript] 빈객체, 객체 타입, 클래스 추가 개념 (0) | 2022.12.26 |
[TypeScript] create-react-app 으로 만든 리액트 앱 TS로 변환 세팅 (0) | 2022.12.06 |
[TypeScript | 타입스크립트 가이드북] TS vs ES6 (0) | 2022.11.28 |
[TypeScript] 타입스크립트의 타입들 (0) | 2022.09.04 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- nvm 설치순서
- text input pattern
- 프리렌더링확인법
- nvm경로 오류
- 항해99추천비추천
- 원티드 프리온보딩 FE 챌린지
- getServerSideProps
- 형제 요소 선택자
- fs모듈 넥스트
- 원티드 3월 프론트엔드 챌린지
- Prittier
- reactAPI
- 항해99프론트
- 타입스크립트 DT
- is()
- float 레이아웃
- 틸드와 캐럿
- D 플래그
- && 셸 명령어
- tilde caret
- 부트캠프항해
- aspect-ratio
- 원티드 프리온보딩 프론트엔드 챌린지 3일차
- ~ ^
- getStaticPaths
- 타입스크립트 장점
- 원티드 FE 프리온보딩 챌린지
- 프리온보딩 프론트엔드 챌린지 3월
- grid flex
- 항해99프론트후기
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함