타입 추론 | 타입 단언 | 타입 가드
2022. 12. 23. 18:55ㆍ프로그래밍/TypeScript
- 목차
타입 추론 (Type Inference)
명시적으로 타입 선언이 되어있지 않을 경우
타입스크립트가 타입을 추론해서 제공함
let num = 12;
num = 'Hello'; // Error. 타입스크립트가 num 변수를 Number 타입으로 추론함
타입 스크립트가 타입을 추론하는 경우
- 초기화된 변수
- 기본값이 설정된 매개 변수
- 반환 값이 있는 함수
// 초기화된 변수 num
let num = 12;
// 기본값이 지정된 매개 변수 b + 반환 값이 확실한 함수 add
function add(a: number, b: number = 2) {
return a + b;
}
타입 추론 !== 엄격하지 않은 타입 선언
타입 추론을 활용해 모든 곳에 타입을 명시하지 않고도 코드 가독성을 높일 수 있음
타입 단언 (Type Assertion)
타입스크립트가 타입 추론을 통해 판단할 수 있는 타입의 범위를 넘을 경우
더 이상 추론하지 않도록 지시하는 것
변수 as 타입
function someFunc(val: string | number, isNumber: boolean) {
if (isNumber) {
// val.toFixed(2) // Error. val 이 string일 수 있음
(val as number).toFixed(2)
// JSX 문법 사용 시 파싱에서 문제 발생 (.tsx 파일에서 사용 불가)
// (<number>val).toFixed(2)
}
}
val.toFixed(2) === 에러 발생
- val 은 string | number 타입이기 때문에 string 일 수도 있음
- string 타입은 toFixed() 사용이 불가능 하기 때문에 에러 발생
val as number === 타입 단언
- val 가 number 타입이라는 것을 명시적으로 단언해 주어야 함
Non-null 단언 연산자
! 를 사용하는 Non-null 단언 연산자
피연산자가 Nullish (null, undefined) 값이 아님을 단언 가능
if 조건문, 타입 단언으로 해결할 수도 있지만 Non-null 연산자를 이용하면 간단함
// Error. x는 null, undefined일 수도 있음
function func(x: number | null | undefined) {
return x.toFixed(2)
}
// if 조건문으로 x가 Truthy 값인지 판별하는 방법
function func(x: number | null | undefined) {
if (x) {
return x.toFixed(2)
}
}
// 타입 단언 (변수 as 타입)
function func(x: number | null | undefined) {
return (x as number).toFixed(2)
}
// Non-null 단언 연산자
function func(x: number | null | undefined) {
return x!.toFixed(2)
}
// Error. null 값일 가능성이 있음
document.querySelector('.item').innerHTML;
// 타입 단언
(document.querySelector('.menu-item') as HTMLDivElement).innerHTML;
(<HTMLDivElement>document.querySelector('.item')).innerHTML;
// Non-null 단언 연산자
document.querySelector('.item')!.innerHTML;
타입 가드 (Type Guard)
NAME is TYPE 형태를 반환 타입으로 명시한 함수
타입스크립트가 추론 가능한 특정 범위에서 타입 보장 가능
// 타입 가드
function isNumber(val: string | number): val is number {
return typeof val === 'number';
}
function func(val: string | number) {
if (isNumber(val)) {
val.toFixed(2);
isNaN(val);
} else {
val.split('');
val.toUpperCase();
val.length;
}
}
// typeof 연산자를 직접 사용한 타입 가드
function someFuncTypeof(val: string | number) {
if (typeof val === 'number') {
val.toFixed(2)
} else {
val.split('')
}
}
// in 연산자를 사용한 타입 가드
function someFuncIn(val: any) {
if ('toFixed' in val) {
val.toFixed(2)
} else if ('split' in val) {
val.split('')
}
}
// instanceof 연산자를 사용한 타입 가드
class Cat {
meow() {}
}
class Dog {
woof() {}
}
function sounds(ani: Cat | Dog) {
if (ani instanceof Cat) {
ani.meow()
} else {
ani.woof()
}
}