방명록
- [TypeScript] TypeScript 공부일지: 서로소 유니온 타입 [6/7 study]2024년 06월 07일 16시 21분 19초에 업로드 된 글입니다.작성자: 동혁이
TypeScript 공부일지: 서로소 유니온 타입
❗️주의
지극히 개인 공부한 내용을 올린 거기 때문에 이해하지 못할 수도 있음
❗️서로소 유니온 타입이란?
- 교집합이 없는 타입들로만 만든 유니온 타입을 말함
- ex) string, number는 교집합이 없음 수학에서는 이런 걸 서로소 집합 이라고 함
- string | number 이런걸 서로소 유니온 타입이라고 부름
/** * 서로소 유니온 타입 * 교집합이 없는 타입들로만 만든 유니온 타입을 말함 * ex) string, number는 교집합이 없음 수학에서는 이런 걸 서로소 집합 이라고 함 * string | number 이런걸 서로소 유니온 타입이라고 부름 */ 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; // Admin => {name}님 {kickCount}명 강퇴했습니다. // Member => {name}님 현재까지 {point}모았습니다. // Guest => {name}님 현재까지 {visitCount}번 오셨습니다. 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; } } // if (user.tag === "ADMIN") { // // 원래 조건문이 "kickCount" in user 이였는데 이제는 user.tag === "ADMIN"이라고 작성하면 직관적임 // // Admin 타입 // console.log(`${user.name}님 ${user.kickCount}명 강퇴했습니다.`); // } else if ("point" in user) { // // Member 타입 // console.log(`${user.name}님 현재까지 ${user.point}모았습니다.`); // } else if ("visitCount" in user) { // // Guest 타입 // console.log(`${user.name}님 현재까지 ${user.visitCount}번 오셨습니다.`); // } // 잘 만들었는데 만약 이걸 다른사람이 보거나 주석도 없다면 이 조건문 내부는 Admin이구나 이걸 아무도 모름 // 결론적으로 코드를 이렇게 작성하면 직관적이지 않음 => 이럴때 서로소 유니온 타입을 사용하면 됨 // 프로퍼티에 tag라는 프로퍼티를 추가할거임 value로는 string 타입이 아니라 string literal type 으로 만들어줌 전부 대문자 사용 } /** * 복습겸 한가지 더 사례 * 비동기 작업 처리 결과를 처리하는 객체 */ type LoadingTask = { state: "LOADING"; }; type FailedTask = { state: "FAILED"; error: { message: string; }; }; type SuccessTask = { state: "SUCCESS"; response: { data: string; }; }; type AsyncTask = LoadingTask | FailedTask | SuccessTask; // { // // state: string; 이거 보다는 // state: "LOADING" | "FAILED" | "SUCCESS"; // error?: { // message: string; // }; // response?: { // data: string; // }; // }; // 로딩중 => 콘솔에 로딩중 출력 // 실패 => 실패: 에러메시지를 출력 // 성공 => 성공: 데이터를 출력 function processResult(task: AsyncTask) { switch (task.state) { case "LOADING": { console.log("로딩중"); break; } case "FAILED": { // task.error?.message 우리는 case를 정확히 FAILED일때로 했는데 error?.에서 물음표를 빼면 오류가 나옴 // task에 마우스 올려보면 task 일때도 AsyncTask로 나옴 타입이 좁혀지지 않았음 // task.state가 FAILED라 하더라도 error 프로퍼티는 선택적 프로퍼티로 정의 되어있기 때문에 // task에 에러가 있는지 없는지 확실히 모름 쉽게 말하면 좁혀질 타입 자체가 없음 타입이 하나밖에 없으니까 // 어쩔수없이 optional chaining 써주던가 non,null단언을 사용해야하는데 이러면 안전한 코드가 아님 // 이럴때는 AsyncTask를 3개의 타입으로 분리해서 서로소 유니온 타입으로 만들어 줘야함 console.log(`에러 발생: ${task.error.message}`); break; } case "SUCCESS": { console.log(`성공: ${task.response.data}`); break; } } } const loading: AsyncTask = { state: "LOADING", }; const failed: AsyncTask = { state: "FAILED", error: { message: "오류 발생 ~", }, }; const success: AsyncTask = { state: "SUCCESS", response: { data: "데이터 ~", }, };
다음글이 없습니다.이전글이 없습니다.댓글