교집합이 없는 타입들로만 만든 유니온 타입
동시에 여러가지 상태를 표현할때는, 상태에 선택적 프로퍼티를 사용하는것보다 타입들을 잘게 뽀게어 state또는 tag 만들어서 직관적으로 확인하는 것을 추천한다.
type Admin = {
name: string;
kickCount: number;
};
type Member = {
name: string;
point: number;
};
type Guest = {
name: string;
visitCount: number;
};
type User = Admin | Member | Guest;
function login(user: User) {
if ("kickCount" in user) {
console.log(`${user.name}님 현재까지 ${user.kickCount}명 추방했습니다`);
} else if ("point" in user) {
console.log(`${user.name}님 현재까지 ${user.point}모았습니다`);
} else {
console.log(`${user.name}님 현재까지 ${user.visitCount}번 오셨습니다`);
}
}
🚨(직관적이지 않다.)이 코드를 다른 사람이보면 어디가 admin, member, guest인지 알 수 없다.
💁♂️ tag 프로퍼티를 만들고, switch문으로 변경
=> 훨씬 직관적
type Admin = {
tag: "ADMIN"
name: string;
kickCount: number;
};
type Member = {
tag: "MEMBER"
name: string;
point: number;
};
type Guest = {
tag: "GUEST"
name: string;
visitCount: number;
};
type User = Admin | Member | Guest;
function login(user: User) {
switch (user.tag){
case "ADMIN": {
console.log(`${user.name}님 현재까지 ${user.kickCount}명 추방했습니다`);
break
}
case "MEMBER": {
console.log(`${user.name}님 현재까지 ${user.point}모았습니다`);
break
}
case "GUEST": {
console.log(`${user.name}님 현재까지 ${user.visitCount}번 오셨습니다`);
break
}
}
}
- 리터럴 타입은 딱 1개의 값만 포함함
비동기 작업의 결과를 처리하는 객체
type LoadingTask = {
state: "Loading";
};
type FailedTask = {
state: "Failed";
error: {
message: string;
};
};
type SuccessTask = {
state: "Success";
response: {
data: string;
};
};
type AsyncTask = LoadingTask | FailedTask | SuccessTask;
//로딩중 => 콘솔에 로딩중 출력
// 실패 -> 실패: 에러메세지
//성공 -> 성공 : 데이터를 출력
function processResult(task: AsyncTask) {
switch (task.state) {
case "Loading": {
console.log(" 로딩 중");
break;
}
case "Failed": {
console.log(`에러발생: ${task.error.message}`);
break;
}
case "Success": {
console.log(`성공 : ${task.response.data}`);
}
}
}
const loading: AsyncTask = {
state: "Loading",
};
const failed: AsyncTask = {
state: "Failed",
error: {
message: "오류 발생 원인은~~",
},
};
const success: AsyncTask = {
state: "Success",
response: {
data: "데이터~~",
},
};