여러 개의 타입으로 지정된 값을 특정 위치에서 원하는 타입으로 구분하는 것을 의미한다.
넓은 타입에서 좁은 타입으로 타입 범위를 좁힌다는 의미로 볼 수 있다.
if문을 사용하여 타입 가드 역할을 하고, if문 안에서는 타입이 string이기 때문에 string에 대한 API를 미리 자동 완성으로 사용할 수 있다.
function updateInput(text: number | string | boolean) {
// 타입 가드
if (typeof text === 'string') {
text~~ // (parameter) text: string
}
}
아래 코드는 유니언 타입으로 정의되어 있기 때문에 해당 타입의 API를 사용하려 하면 에러가 발생하게 된다.
function updateInput(text: number | string | boolean) {
text~~ // (parameter) text: number | string | boolean
}
as키워드를 사용하여 text의 타입을 number로 단언한다.
function updateInput(text: number | string | boolean) {
(text as number).toFixed(2);
}
타입 에러는 해결되지만, 두 가지의 문제가 발생한다.
실행 시점의 에러는 막을 수 없다.
타입 단언을 계속 사용해야 한다.
number타입 API인 toFiexd를 사용하고 string타입 API인 length를 사용하기 위해서 as키워드를 반복적으로 사용해야 한다.
function updateInput(text: number | string | boolean) {
(text as number).toFixed(2);
console.log((text as string).length)
}
if문을 사용하여 타입 가드를 사용한다.
function updateInput(text: number | string | boolean) {
if (typeof text === 'number') {
text.toFixed(2);
return;
}
if (typeof text === 'string') {
console.log(text.length);
return;
}
}
타입 가드에 주로 사용하는 연산자
typeof
연산자 뒤에 붙은 값의 타입을 반환해준다.
if문과 함께 사용하여 특정 위치에서 원하는 타입으로 구분할 수 있다.
const name = 'jonghyun';
if (typeof name === 'string') {
...
}
instanceof
변수가 대상 객체의 프로토타입 체인에 포함되는지 확인하여 true / false를 반환해준다.
주로 클래스 타입이 유니언 타입으로 묶여 있을 때 타입을 구분하기 위해 사용한다.
class Person {
name: string;
age: number;
constructor(name, age) {
this.name = name;
this.age = age;
}
}
function getProfile(profile: Person | string) {
if (profile instanceof Person) {
profile.name~~~
profile.age~~~
}
}
in
객체에 특정 속성이 있으면 true, 없으면 false를 반환해준다.
인터페이스 2개가 유니언 타입으로 연결되어 있을 때 특정 인터페이스로 구분할 수 있다.
같은 속성을 가진 인터페이스는 타입 가드 역할을 할 수 없다.
name의 경우 두 인터페이스 모두 가지고 있으므로 타입 가드의 역할을 할 수 없다.
둘중의 하나만 가지고 있는 속성을 통해서만 타입 가드의 역할을 할 수 있다.
interface Book {
name: string;
rank: string;
}
interface Online {
name: string;
url: string;
}
function learnCourse(material: Book | Online) {
if ('url' in material) {
// 이 블록 안에서는 material이 Online 타입으로 간주된다.
}
}
isPerson함수는 Me, Person, Developer의 유니언 타입을 파라미터로 받고, Person타입인지 아닌지 결과 값으로 반환해준다.
is키워드를 사용할 수 있고, is뒤에 붙은 타입의 속성을 확인 한 후 해당 속성이 존재한다면 해당 타입으로 간주하라는 의미이다.
interface Me {
name: string;
nickName: string;
}
interface Person {
name: string;
age: number;
}
interface Developer {
name: string;
age: string;
skill: string;
}
// 타입 가드 함수
function isPerson(someone: Me | Person | Developer): someone is Person {
return typeof (someone as Person).age === 'number'
}
function getAge(someone: Me | Person | Developer) {
if (isPerson(someone)) {
console.log(someone.age);
}
}
interface Person {
name: string;
age: number;
industry: 'common';
}
interface Developer {
name: string;
age: number;
industry: 'tech';
}
function getIndustry(someone: Person | Developer) {
if (someone.industry === 'tech') {
someone // (parameter) someone: Developer
}
}
interface Person {
name: string;
age: number;
industry: 'common';
}
interface Developer {
name: string;
age: string;
industry: 'tech';
}
function getIndustry(someone: Person | Developer) {
switch (someone.industry) {
case 'common':
console.log(someone.age.toFixed(2));
break;
case 'tech':
console.log(someone.age.length);
break;
}
}
파라미터 타입이 string과 null의 유니언 타입인데 null체크를 하여 null이 아닐때만 message를 출력해줄 수 있다.
null아님 보장 연산자(!)를 사용할 수도 있다.
function sayHello(message: string | null) {
if (message === null) return;
if (message.length >= 3) {
console.log(message)
}
}
function sayHello(message: string | null) {
if (message!.length >= 3) {
console.log(message)
}
}
위의 코드들 대신에 &&연산자(논리 / 비교 연산자)를 사용하여 타입 가드를 할 수 있다.
&&연산자는 양쪽의 모든 항이 true여야 하기 때문에 null체크와 동시에 타입 단언을 사용하지 않고 타입 가드를 할 수 있다.
function sayHello(message: string | null) {
if (message && message.length >= 3) {
console.log(message)
}
}
출처: 쉽게 시작하는 타입스크립트