컴파일러가 타입을 예측할 수 있도록
타입을 좁혀(narrowing)
type safety
방식을 보장
Type Guard
는 데이터의 타입을 알 수 없거나, 될 수 있는 타입이 여러 개라고 가정할 때 조건문을 통해 데이터의 타입을 좁혀나가는 것이다.
Type Guard
로 인해 아래와 같은 장점을 얻을 수 있다.
- 데이터의 타입에 따라 대응하여 에러를 최소화
- 타입을 통해 '가드'하는 코드, 방어적인 코드를 작성
Type Guard
에서 사용되는 built-in
연산자 종류는 다음과 같다.
TypeScript
는 JavaScript
의 typeof
연산자를 이해할 수 있다.
즉, 조건문에 typeof
를 사용하면, TypeScript
는 해당 조건문 블록 내에서 해당 변수 타입이 다르다는 것(=좁혀진 범위의 타입)
을 이해할 수 있다.
function doSomething(x: number | string) {
if (typeof x === 'number') {
console.log(x.toString());
}
x.substr(1); // Error, `x`는 `string`이라는 보장이 없다.
}
TypeScript
는 위의 typeof
와 마찬가지로 instanceof
연산자 또한 이해할 수 있다.
이를 통해 if문
으로 타입을 하나 좁혀나가면, else문
안의 변수 타입은 절대 동일한 타입이 될 수는 없음을 인지한다.
class Delveloper {
name = 'dev';
}
class Person {
age = 10;
}
function doSomething(arg: Delveloper | Person) {
if (arg instanceof Delveloper) {
console.log(arg.name);
console.log(arg.age); // Error!
}
else {
console.log(arg.name); // Error!
console.log(arg.age);
}
}
in
은 객체 내부에 특정 property
가 존재하는지 확인하는 연산자로 Type Guard
로 활용할 수 있다.
interface A {
x: number;
}
interface B {
y: string;
}
function doStuff(q: A | B) {
if ('x' in q) {
// q: A
}
else {
// q: B
}
}
Literal
값의 경우 ===
, ==
, !==
, !=
연산자를 이용하여 타입을 구분할 수 있다.
이는 union
타입에 리터럴 타입이 있는 경우에도 동일하게 적용되며, union
타입의 공통 property
값을 비교해 union
타입을 구분할 수 있다.
type Delveloper = { // 리터럴 타입
name: 'dev',
skill: string
}
type Person = { // 리터럴 타입
name: 'mirrer',
age: number
}
function doSomething(arg: Delveloper | Person) {
if (arg.name === 'dev') {
console.log(arg.skill);
console.log(arg.age); // Error
}
else {
console.log(arg.skill); // Error!
console.log(arg.age);
}
}
TypeScript
는 == null
, != null
의 식으로 null
과 undefined
모두 걸러낼 수 있다.
function doSomething(a?: number | null) {
if (a == null) return;
// a는 number
}
JavaScript
언어는 풍부한 런타임 내부 검사(=runtime introspection support)
를 지원하진 않는다.
하지만 TypeScript
에서는 사용자 정의 Type Guard
함수를 만들어 이를 해결할 수 있다.
// 일반적인 Interface
interface Developer {
name: string;
skill: string;
}
interface Person {
name: string;
age: number;
}
// 사용자 정의 Type Guard
function isPerson(arg: any): arg is Person {
return arg.age !== undefined;
}
// 사용자 정의 Type Guard 사용
function doSomething(arg: Developer | Person) {
if (isPerson(arg)) {
console.log(arg.age);
console.log(arg.skill); // Error
} else {
console.log(arg.age); // Error
console.log(arg.skill);
}
}
doSomething({ name: 'name', skill: 'typescript' });
doSomething({ name: 'name', age: 123 });
TypeScript: JavaScript With Syntax For Types.
React TypeScript Tutorial for Beginners - Codevolution
타입스크립트 입문 - 기초부터 실전까지 - 장기효