솔미는 성장중
[TS] 타입 가드 본문
💻 타입 가드
여러 개의 타입으로 지정된 값을 특정 위치에서 원하는 타입으로 구분하는 것
💻 타입 가드가 필요한 이유
-/-예를 들어 number | string | boolean 타입으로 지정되어있다면 세 타입 모두에서 사용할 수 있는 속성과 API만 접근 가능하다. 즉, toUpperCase, toFixed() 등의 메소드를 사용할 수 없다.
해결 방법)
1. 타입 가드 사용하기 (다음 섹션에서 자세히 설명)
2. 타입 단언으로도 해당 문제를 해결 가능
//예시
function updateInput (textInput: number | string | boolean) {
(textInput as number).toFixed(3);
}
하지만 문제점!
- 실행 시점의 에러를 막을 수 없다.
- 타입 단언을 계속해서 사용해야 한다 (반복적인 코드)
💻 사용하는 주요 연산자
typeof
if문과 함께 사용해 타입 가드 역할을 수행할 수 있다.
//함수 내에서
if( typeof textInput === 'number'){
//~~내용~~;
return;
}
if( typeof textInput === 'string'){
//~~내용~~;
return;
}
instanceof
변수가 대상 객체의 프로토타입 체인에 포함되어있는지 확인해 true/false 반환
연산자 작동방식)
function User(name,age){
this.name=name;
this.age=age;
}
let person1 = new Person('솔미', 100);
person1 instanceof User; // true
let person2 = {name: '철수', age: 90);
person2 instanceof User; // false
instanceof로 타입 가드)
function fetchIfoByProfile(profile: Person | string){
if(profile instanceof Person){
//여기 안에선 profile타입이 Person 타입으로 간주됨
}
}
in
객체에 특정 속성이 있으면 true, 없으면 false
in 연산자를 이용해 인터페이스 2개가 유니언 타입으로 연결되어 있을 때 특정 인터페이스로 구분 가능
(단, 특정 속성이 두 인퍼테이스 모두에 있으면 특정 타입으로 구분해 주지 않는다. = 타입 가드 역할 X)
function fetchIfoByProfile(profile: Person | Image){
if('url' in profile){
//url은 Image란 interface내에만 있는 속성이었음.
//그래서 이 블록 안에서는 profile의 타입이 Image로 간주됨.
}
}
💻 타입 가드 함수
주로 객체 유니언 타입 중 하나를 구분하는 데 사용. (in 연산자와 유사. but 복잡한 경우에도 사용 가능)
예시) 두 인터페이스에서 공통으로 갖고 있는 속성명.(age) 하지만 다른 속성값.(하나는 number, 다른 하나는 string)
특정 인터페이스에서의 속성을(age:number) 출력하고 싶다면?
interface Hero{
name:string;
nickname: string;
}
interface Person{
name:string;
age: number;
}
interface Developer{
name:string;
age: string;
skill: string;
}
function isPerson(someone: Hero | Person | Developer): someone is Person {
return typeof (someone as Person).age === 'number';
}
function greet(someone: Hero | Person | Developer){
if(isPerson(someone)){
console.log(someone.age); //Person타입으로 추론. age속성 타입은 number가 된다.
}
}
💻 구별된 유니언 타입
유니언 타입을 구성하는 여러 개의 타입을 특정 속성 유무가 아니라 특정 속성 값으로 구분하는 타입 가드 문법
예제)
interface Person {
name: string;
age:number;
industry: 'common';
}
interface Developer {
name: string;
age:string;
industry: 'tech';
}
function greet(someone: Person | Developer) {
if(someone.industry === 'common') {
//someone의 타입은 Person 타입으로 추론됨.
}
}
industry 속성에 문자열 타입이 각각 common과 tech로 선언되어서 구분가능 했다.
💻 switch 문과 연산자
앞선 예제를 수정)
interface Person {
name: string;
age:number;
industry: 'common';
}
interface Developer {
name: string;
age:string;
industry: 'tech';
}
function greet(someone: Person | Developer) {
switch(someone.industry) {
case 'common':
//someone의 타입은 Person 타입으로 추론됨.
break;
case 'tech':
//someone의 타입은 Developer 타입으로 추론됨.
break;
}
}
💻 논리 비교 연산자
function sayHi(message: string | null){
if(message && message.length >=3){ //message값이 있는지를 확인해주면서 타입 가드 적용 효과
console.log(message);
}
}
////////////////////////////////////////
//같은 기능 다른 방식 : ! 사용하기
function sayHi(message: string | null){
if(message!.length >=3){ //null아님 보장 연산자를 이용해 string타입으로만 간주되게.
console.log(message);
}
}
//같은 기능 다른 방식 : if구문으로 null 걸러주기
function sayHi(message: string | null){
if(message === null){ //null일 땐 그냥 반환
return;
}
if(message.length >=3){
console.log(message);
}
}
'TypeScript' 카테고리의 다른 글
[TS] 함수 오버로딩 (overloading) / 접근 제어자(public, protected, private) (0) | 2023.10.02 |
---|---|
[TS] 타입 호환 (0) | 2023.08.31 |
[TS] 타입 단언 (0) | 2023.08.30 |
[TS 2주차] 제네릭이란 무엇인가! (+ 제네릭을 제한하려면..?) (0) | 2023.08.23 |
[TS 2주차] 타입 별칭 vs 인터페이스 : 차이점은 무엇이고, 무엇을 써야하는가! (0) | 2023.08.22 |