TypeScriptSTUDY _ 4장 . 타입 확장하기 . 좁히기 [ 4.3 타입 좁히기 - 식별할 수 있는 유니온 Discriminated Unions ]

zeroha·2024년 12월 2일
0

TypeScriptStudy

목록 보기
12/32
post-thumbnail

4.3 타입 좁히기 - 식별할 수 있는 유니온 Discriminated Unions

= 태그된 유니온 Tagged Union
: 타입 좁히기에 널리 사용되는 방식

.
.
.

1. 에러 정의하기

: 유효성 검사
유효성 에러 발생 -> 에러코드 & 에러메시지
이때, 에러 노출 방식데 따라 추가 필요정보 필요 가능

  • 에러 타입
type TextError = {
  errorCode: string;
  errorMessage: string;
};

type ToastError = {
  errorCode: string; 
  errorMessage: string;
  toastshowDuration: number; // 토스트를 띄워줄 시간
};

type AlertError = {
  errorCode: string;
  errorMessage: string;
  onConfirm: O=> Void; / 얼럿 창의 확인 버튼을 누른 뒤 액션
};
  • 에러 타입의 유니온 타입을 원소로 배열 정의
type ErrorFeedbackType = TextError | ToastError | AlertError;
const errorArr: ErrorFeedbackType[] = [
  { errorCode: "100", errorMessage: "텍스트 에러" }, 
  { errorcode: "200", erroressage: "토스트 에러", toastShowburation: 3000 }, 
  {errorcode: "300", errortessage: "얼럿 에러", onConfirm: ()=> {} },
  ];

ErrorFeedbackType의 원소를 갖는 배열 errorArr를 정의 -> 다양한 에러 객체 관리 가능

  • 여기서 해당 배열에 에러 타입별로 정의한 필드를 가지는 에러 객체가 포함되길 원한다 가정할 때.
    : 객체 =ToastError의 toastShowburation 필드 + AlertError의 onConfirm 필드
    -> 타입 에러를 뱉어야 함.
const errorArr: ErrorFeedbackType[] = [
  //...
  {
  errorCode: "999",
  errorMessage: "잘못된 에러",
  toastShowDuration: 3000, 
  onConfirm: () => {},
  }, // expected error
 ];  
  • 자바스크립트 = 덕 타이핑 언어
    : 별도의 타입 에러를 뱉지 않는 걸 확인 가능.

-> 타입 에러가 발생하지 않는다면 무수한 에러 객체가 생겨날 위험성 높아짐.


2. 식별할 수 있는 유니온

  • 에러 타입을 구분할 방법 필요
    : 타입들이 서로 포함관계를 가지지 않도록 정의해야 함 -> 식별할 수 있는 유니온을 활용해야 함.
    : 타입 간의 구조 호환을 막기 위해 타입마다 구분할 수 있는 판별자를 달아주어 포함 관계를 제거.
  • errorType이라는 새로운 필드를 새롭게 정의
    ( 각 에러 타입마다 이 필드에 대해 다른 값을 가지도록 하여 판별자를 달아주면 이들은 포함관계를 벗어나게 됨. )
type TextError = {
  errorType: "TEXT"; 
  errorCode: string;
  errorMessage: string;
}
  type ToastError = {
    errorType: "TOAST";
    errorCode: string; 
    errorMessage: string;
    toastShowDuration: number;
}

type AlertError = {
  errorType: "ALERT"; 
  errorCode: string; 
  errorMessage: string; 
  onConfirm: () => void;
};
  • 여러 객체 타입을 정의한 상태에서 errorArr를 새로 정의
type ErrorFeedbackType = TextError | ToastError | AlertError;
const errorArr: ErrorFeedbackType[] = [
  {errorType: TEXT errorCode: "100", errorMessage: "텍스트 에러" },
 {
   errorType: "TOAST", 
   errorCode: "200",
   errorMessage: "토스트 에러",
   toastShowDuration: 3000,
},
{
  errorType: "ALERT", 
  errorCode: "300",
  errorMessage: "얼럿 에러",
  onConfirm: () => {},
},
{
    errorType: "TEXT", 
    errorCode: "999",
    errorMessage: "잘못된 에러",
    toastShowDuration: 3000, // Object Literal may only specify known properties, and 'toastShowDuration' does not exist in type 'TextError'
      onConfirm: () => {},
},
{
  errorType: "TOAST", 
  errorCode: "210",
  errorMessage: "토스트 에러",
  onConfirm: () => {}, // Object Literal may only specify known properties, and 'onConfirm' does not exist in type 'ToastError'
},
{
  errorType: "ALERT", 
  errorCode: "310",
  errorMessage: "얼럿 에러",
  toastShowDuration: 5000, // Object Literal may only specify known properties, and 'toastShowDuration' does not exist in type 'AlertError'
},
  ];

: 정확하지 않은 여러 객체에 대해 타입 에러가 발생하는 것 확인 가능.


3. 식별할 수 있는 유니온의 판별자 선정

식별할 수 있는 유니온을 사용할 때 주의점 )
: 식별할 수 있는 유니온의 판별자는 유닛타입 unit type으로 사용되어야 정상 작동함.

유닛 타입 unit type
: 다른 타입으로 쪼개지지 않고 오직 하나의 정확한 값을 가지는 타입
null, undefined, 리터럴 타입을 비롯해 true, 1
<-> 다양한 타입 할당 : void, string, number

  • 유니온 판별자
    : 리터럴 타입이어야 함.
    : 판별자 값 = 적어도 하나 이상의 유닛 타입 포함 & 인스턴스화할 수 있는 타입 instantiable type은 포함되지 않아야 함.
interface A {
  value: "a"; // unit type 
  answer: 1;
}

interface B {
  value: string; // not unit type 
  answer: 2;
}

interface C {
  value: Error; // instantiable type 
  answer: 3;
}

type Unions = A | B | C;
function handle(param: Unions) {
/**판별자가 value일 때 */
  param.answer; // 1 | 2 | 3
  
  // a 가 리터럴 타입이므로 타입이 좁혀진다.
  // 단, 이는 String 타입에 포함되므로 param은 A 또는 B 타입으로 좁혀진다
  if (param.value === "a") { param.answer; // 1 | 2 return;
}
                                                    
// 유닛 타입이 아니거나 인스턴스화할 수 있는 타입일 경우 타입이 좁혀지지 않는다
if (typeof param.value === "string") {
   param.answer; // 1 | 2 | 3 return;
}
if (param.value instanceof Error) {
param.answer; // 1 | 2 | 3 return;
}
/**: 판별자가 answer일 때 */
param.value; // string | Error
  
// 판별자가 유닛 타입이므로 타입이 좁혀진다
if (param.answer === 1) {
  param.value; // 'a'
	}
}
  • 판별자 = value
    : 판별자로 선정한 값 중 'a'만 유일하게 유닛 타입.
    이때만 유닛 타입 포함해서 -> 타입이 좁혀짐.

  • 판별자 = answer
    : 판별자가 모두 유닛 타입 -> 타입이 정상적으로 좁혀짐.


도서참조 : 우아한 타입스크립트 with 리액트

profile
하 영

0개의 댓글

관련 채용 정보