Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[01/17] 4장 #75

Open
2yunseong opened this issue Jan 15, 2024 · 0 comments
Open

[01/17] 4장 #75

2yunseong opened this issue Jan 15, 2024 · 0 comments
Assignees

Comments

@2yunseong
Copy link
Contributor

우아한 3장

difference between extend and Intersect

intersect와 extends의 차이는, extends 는 호환되지 않는 타입에 대해서는 오류를 발생 시킨다.

interface Parent {
    a: number;
}

interface Child extends Parent { // Error: ts2430
    a: string;
}

비슷하게 interface는 선언 병합이라는 것으로도 흉내낼 수 있다.

interface Parent {
  a:number;
}

interface Parent {
  b:number;
}

하지만 intersect는 never로 평가한다.

/* 각 타입의 a의 타입이 number, string 일 때 */
type Merge = Parent & Child; /* {  a:never  } */

diferrence between added property and extend

// case1. 타입 속성 추가
interface Menu {
  name:string;
	image:string;
	gif?:string;
	text?:string;
}
// case2. 타입 확장
interface Menu {
	name:string;
	image:string;
}

interface SpecialMenu extends Menu {
	gif:string;
}

interface PackageMenu extends Menu {
	text:string;
}

case1. add property

추가로 접근할 때는 SpecialMenu처럼 사용하고 싶을 때는 항상 타입 좁히기 를 해주어야한다.

if(!menu.gif) {
	// gif 속성이 있는 Menu를 사용할 수 있다.
}

case2. extends

물론 타입 확장을 사용해도 특정 타입 처럼 사용할 때는 좁혀야 하긴 하지만, 특정된 타입만 사용할 때는 특정 타입으로 선언할 수 있다는 장점이 있다.

const specialMenus:SpecialMenu[] = [{ ... }] // SpecialMenu의 속성을 바로 사용할 수 있다.

specialMenus[0].gif // OK!

type narrowing

  • 런타임에서도 타입을 안전하게 사용하는 방법을 알아야 한다. (컴파일 해도 타입 정보가 사라지지 않는 법을 강구해야 한다.)
  • 원시타입을 추론할 때는 typeof를 사용할 수 있다.
    • 원시타입이 아닌 경우에는 typeof는 생각과 다르게 동작할 수 있으니 주의해야 한다.
  • 인스턴스화된 객체를 추론할 때는 instanceof 연산자를 활용할 수 있다.
  • 객체에 속성이 있는지 없는지를 구분하려면 in 연산자를 활용할 수 있다.
    • 유니온 타입을 좁힐 때 유용하다

type predicates(타입 명제)

  • 타입 좁히기를 할 때, 스코프를 좁히기 위한 조건을 함수화해 사용하는 것
  • is 키워드 사용
  • parameter is return value 로 사용

Discriminated Unions

  • 태그된 유니온(Tagged Union)이라고도 불림
  • 보통 유니온 타입의 원소에 식별할 수 있는 판별자(discriminant)를 넣음
  • 판별자는 서로 다르므로 타입 좁히기 시 유용하게 사용가능
interface TypeError {
	eType: 'TYPE';
	errMsg: string;
	line: number;
}

interface NetworkError {
	eType: 'NETWORK';
	errMsg:string;
	line: number;
	httpStatus: number;
}

// discriminat로 판별할 수 있는 Union이 된다.
type MyError = TypeError | NetworkError ;

주의사항

  • 리터럴 타입 이여야 한다.
    • 덕 타이핑이라는 특성 때문에..

쉽게 말해, 식별할 수 있는 단 한가지의 값으로 판별자를 사용하자.

Exhaustiveness Checking

  • 모든 상황에 대해 타입 체킹을 하는 과정
  • 예상치 못한 런타임 에러를 방지할 수 있음

모든 케이스를 작성해주지 않는다면, params에 never가 아닌 string이 들어가므로 옳지않다.

따라서 모든 ProductPrice에 대한 대응을 해주어야하고, 그 의미에 맞게 switch문으로 변경해보았다.

type ProductPrice = "10000" | "20000" | "5000";

const exhaustiveCheck = (params:never):never => {
    throw new Error("존재하지 않는 상품권 수량입니다.")
};

const getProductName = (productPrice:ProductPrice): string => {
    switch(productPrice) {
        case "10000":
            return "배민 상품권 일만원";
        case "20000":
            return "배민 상품권 이만원";
        case "5000":
            return "배민 상품권 오천원";
        default:
            return exhaustiveCheck(productPrice);
    }
}

이야기

  • 각 타입 좁히기의 방법을 어떤 상황에 적용하면 좋을 지, 또는 적용되어 있는지 같이 이야기 해봐요
@2yunseong 2yunseong self-assigned this Jan 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant