Typescript - 고급타입
인터렉션 타입
type Admin = {
name: string;
privileges: string[];
};
type Employee = {
name: string;
startDate: Date;
};
type ElevatedEmployee = Admin & Employee;
타입 가드
type Combinable = string | number;
function add(a: Combinable, b: Combinable){
if(typeof a === 'string' || typeof b === 'string'){ // 타입가드
return a.toString() + b.toString();
}
return a + b; // a와 b가 숫자형이어야 한다는 것을 안다.
}
- 타입가드는 유니온 타입이 지닌 유연성을 활용할 수 있게 해주며 런타임 시 코드가 정확하게 작동하게 해준다.
type Admin = {
name: string;
privileges: string[];
};
type Employee = {
name: string;
startDate: Date;
};
type UnknownEmployee = Employee | Admin;
function printEmployeeInformation(emp: UnknownEmployee){
console.log('Name: '+emp.name);
if('privileges' in emp){
console.log('Privileges: '+ emp.privileges);
}
if('startDate' in emp){
console.log('Start Date: '+ emp.startDate);
}
}
- 사용자정의타입 유니온일 때.
class Car {
drive() {
console.log('Driving...');
}
}
class Truck {
drive() {
console.log('Driving a truck...');
}
loadCargo(amount: number) {
console.log('Loading cargo ...' + amount);
}
}
type Vehicle = Car | Truck;
const v1 = new Car();
const v2 = new Truck();
function useVehicle(vehicle: Vehicle){
vehicle.drive();
// if('loadCargo' in vehicle){
// vehicle.loadCargo(1000);
// }
if(vehicle instanceof Truck){
vehicle.loadCargo(1000);
}
}
useVehicle(v1);
useVehicle(v2);
- 클래스를 사용하여 작업하는 경우 다른 유형의 타입가드도 사용할 수 있다.
- instanceof 타입가드를 이용
- instanceof 를 사용하면 객체가 클래스에 기반하는지 확인할 수 있고, 클래스에 기반한다면 loadCargo 함수를 지니고 있는지 확인할 수 있다.
- 결국 타입가드는 특정 속성이나 메소드를 사용하기 전에 그것이 존재하는지 확인하거나 타입을 사용하기 전에 이 타입으로 어떤 작업을 수행할 수 있는지를 확인하는 개념 또는 방식을 나타내는 용어이다
- 객체의 경우 instanceof 나 in을 사용하여 수행할 수 있고, 다른 타입들의 경우 typeof를 사용할 수 있다
구별된 유니언
interface Bird {
type: 'bird';
flyingSpeed: number;
}
interface Horse {
type: 'horse';
runningSpeed: number;
}
type Animal = Bird | Horse;
function moveAnimal(animal: Animal){
let speed;
switch (animal.type){
case 'bird':
speed = animal.flyingSpeed;
break;
case 'horse':
speed = animal.runningSpeed;
break;
}
console.log('Moving at speed: '+ speed);
}
moveAnimal({type: 'bird', flyingSpeed: 10});
- 타입 가드를 쉽게 구현할 수 있게 해주는 유니언 타입으로 작업을 수행할 때 사용할 수 있는 패턴으로 객체 타입으로 작업할 때도 사용할 수 있다.
- 인터페이스를 기반으로 구축된 모든 객체가 해당 타입을 갖도록 한다
- 주어진 속성의 존재 여부를 확인하거나 instanceof를 사용하게 아닌 실제 존재하는 속성을 사용하여 어떤 유형의 객체와 작업하고 있는지 확인할 수 있다.
- 객체와 유니언 타입을 사용하여 작업할 때 아주 유용한 패턴이라 할 수 있다.
형변환 ( typecasting )
- 형 변환은 타입스크립트가 직접 감지하지 못하는 특정 타입의 값을 타입스크립트에 알려주는 역할을 한다.
// const userInputElement = <HTMLInputElement>document.getElementById('user-input')!;
const userInputElement = document.getElementById('user-input')! as HTMLInputElement;
userInputElement.value = 'Hi there!';
const userInputElement = document.getElementById('user-input');
if ( userInputElement ) {
(userInputElement as HTMLInputElement).value = 'Hi there!';
}
- 어떤 표현식이 반환하든 타입이 되도록 반드시 확인해야한다.
- 이와 달리 지원되지 않는 방식으로 해당 요소와 상호 작용하려하면 런타임 에러가 발생하거나 예기치 않은 동작이 런타임 시 발생할 수 있다.
- 느낌표를 사용하여 느낌표 앞의 표현식을 null을 반환(yield)하지 않겠다고 타입스크립트에게 인식시킬 수 있다.
인덱스 속성
interface ErrorContainer { // { email: 'Not a valid email', username: 'Must start with a character!' }
[prop: string]: string;
}
const errorBag: ErrorContainer = {
email: 'Not a valid email!',
username: 'Must start with a capital character!'
};
- 유연성을 제공하기에 사용하고자 하는 속성 이름과 필요한 속성의 개수를 미리 알 필요가 없다.
함수 오버로드
- 동일한 함수에 대해 여러 함수 시그니처를 정의할 수 있는 기능으로, 간단히 말해 다양한 매개변수를 지닌 함수를 호출하는 여러가지 가능한 방법을 사용하여 함수 내에서 작업을 수행할 수 있게 해준다.
function add(a: number, b: number): number;
function add(a: string, b: string): string;
function add(a: string, b: number): string;
function add(a: number, b: string): string;
function add(a: Combinable, b: Combinable){
if(typeof a === 'string' || typeof b === 'string'){
return a.toString() + b.toString();
}
return a + b;
}
const result = add('Max','Schwarz');
result.split(' ');
선택적 체이닝
- 정의되어 있는지 여부가 확실치 않은 요소 다음에 물음표를 추가
- 해당 부분이 존재하는지를 알려준다.
const fetchedUserData = {
id: 'u1',
name: 'Max',
job: {title: 'CEO', description: 'My own company'}
};
console.log(fetchedUserData?.job?.title);
- 선택적 체이닝 연산자는 객체 데이터의 중첩된 속성과 객체에 안전하게 접근할 수 있게 해준다.
Null 병합
- null 데이터 처리에 도움을 주는 null 병합이라는 기능
- 어떤 데이터나 입력값이 있는데 그것이 null인지, undefined인지, 유효한 데이터인지 알 수 없을 경우,
논리적 OR 연산자 사용
const userInput = null;
const storedData = userInput || 'DEFAULT';
- 이 방법의 문제는 이것이 null이나 undefined가 아닌 빈 문자열이라도 거짓 같은 값으로 처리되어 기본 폴백 값이 적용됨.
이중 물음표 연산자
const userInput = '';
const storedData = userInput ?? 'DEFAULT';
- null 병합 연산자
- null 이나 undefined 둘 중 하나라면 폴백을 사용, 빈문자열 허용