#37 공식 명칭에는 상표를 붙이기

2023. 3. 13.·🎨 프론트엔드 공부/JS & TS

이펙티브 타입스크립트 (댄 밴더캄 지음) 를 읽고 정리

📍요약

✅구조적 타이핑 때문에 값의 타입을 세밀하게 구분하지 못할 때가 있다

이 때 상표를 붙이는 것을 고려할 수 있다

 

✅상표 기법은 타입 시스템에서만 동작하지만, 런타임에서 상표를 검사하는 것과 동일한 효과를 얻을 수 있다

 

📍상표(brand) 붙이기

아래 코드에서는 구조적 타이핑으로 calculateNorm의 매개변수 자리에 Vector2D가 아닌 3D 타입도 에러없이

가능하게 된다

interface Vector2D {
  x: number;
  y: number;
}
function calculateNorm(p: Vector2D) {
  return Math.sqrt(p.x * p.x + p.y * p.y);
}

calculateNorm({x: 3, y: 4});  // OK, result is 5
const vec3D = {x: 3, y: 4, z: 1};
calculateNorm(vec3D);  // OK! result is also 5

 

calculateNorm 함수가 Vector2D만 갖게 하려면 상표를 붙이면 된다

_brand 프로퍼티를 넣어 다른 비슷한 타입이 매개변수로 들어오는 것을 걸러낼 수 있다

interface Vector2D {
  _brand: '2d';
  x: number;
  y: number;
}
function vec2D(x: number, y: number): Vector2D {
  return {x, y, _brand: '2d'};
}
function calculateNorm(p: Vector2D) {
  return Math.sqrt(p.x * p.x + p.y * p.y);  // Same as before
}

calculateNorm(vec2D(3, 4)); // OK, returns 5
const vec3D = {x: 3, y: 4, z: 1}; // _brand: '2d' 프로퍼티를 as const로 넣으면 가능하긴 함..
calculateNorm(vec3D);
           // ~~~~~ Property '_brand' is missing in type...

 

 

⭐그런데, 이것도 _brand: '2d' 프로퍼티를 as const로 넣으면 회피할 수 있다..

 

📍절대경로와 상대경로 체크하는 예제

- 타입가드 (f 함수) 를 활용하여 분기

- 타입가드 대신 타입 단언문을 사용할 수도 있지만, (path as AbsolutePath)

타입 단언문은 지양하는 것이 좋다

⭐타입 단언문을 쓰지 않고 AbsolutePath 타입을 얻는 방법

- AbsolutePath 타입을 매개변수로 받음

- 타입 가드를 통해 맞는지 체크

type AbsolutePath = string & {_brand: 'abs'}; // & : intersection type
function listAbsolutePath(path: AbsolutePath) {
  // ...
}
function isAbsolutePath(path: string): path is AbsolutePath { // is : 반환값의 타입을 정의
  return path.startsWith('/');
}
function f(path: string) {
  if (isAbsolutePath(path)) {
    listAbsolutePath(path); // path가 AbsolutePath 타입이 확실한 경우
  }
  // 아래는 path가 string 일 수 있을 경우
  listAbsolutePath(path);
                // ~~~~ Argument of type 'string' is not assignable
                //      to parameter of type 'AbsolutePath'
}

 

📍매개변수를 제한하기 위해 상표를 사용하는 예제

- 이진 탐색 코드

매개 변수는 정렬된 배열이어야 함

function binarySearch<T>(xs: T[], x: T): boolean {
  let low = 0, high = xs.length - 1;
  while (high >= low) {
    const mid = low + Math.floor((high - low) / 2);
    const v = xs[mid];
    if (v === x) return true;
    [low, high] = x > v ? [mid + 1, high] : [low, mid - 1];
  }
  return false;
}

 

매개변수가 정렬된 배열임을 증명하기 위해 상표 기법을 활용

- SortedList

type SortedList<T> = T[] & {_brand: 'sorted'};

function isSorted<T>(xs: T[]): xs is SortedList<T> {
  for (let i = 1; i < xs.length; i++) {
    if (xs[i] > xs[i - 1]) {
      return false;
    }
  }
  return true;
}

function binarySearch<T>(xs: SortedList<T>, x: T): boolean {
  // COMPRESS
  return true;
  // END
}

 

📍number 타입에 상표 붙이기

- number 타입에 붙일 수 있지만 단언문을 써야 한다

산술 연산 후에 타입이 다시 number로 바뀌지만, 여러 단위가 혼재하는 코드를 문서화 할 때 괜찮을 수 있음

type Meters = number & {_brand: 'meters'};
type Seconds = number & {_brand: 'seconds'};

const meters = (m: number) => m as Meters;
const seconds = (s: number) => s as Seconds;

const oneKm = meters(1000);  // Type is Meters
const oneMin = seconds(60);  // Type is Seconds
// 산술 연산 이후에 타입이 number로 변함
const tenKm = oneKm * 10;  // Type is number
const v = oneKm / oneMin;  // Type is number

 

 

'🎨 프론트엔드 공부/JS & TS' 카테고리의 다른 글
  • #39 any를 구체적으로 변형해서 사용하기
  • #38 any 타입은 가능한 좁은 범위에서만 사용하기
  • #36 해당 분야의 용어로 타입 이름 짓기
  • #35 데이터가 아닌, API와 명세를 보고 타입 만들기
지식물원
지식물원
지식이 자라는 식물원!
  • 지식물원
    지식물원
    지식물원
  • 전체
    오늘
    어제
    • 분류 전체보기 (510)
      • 🎨 프론트엔드 공부 (247)
        • JS & TS (86)
        • HTML & CSS (22)
        • React & Next (49)
        • Vue & Nuxt (22)
        • 기타 (68)
      • 🤓 기술 학습 & 공부 기록 (116)
        • Node.js (0)
        • Python (37)
        • 백엔드 (0)
        • 딥러닝 (1)
        • 컴퓨터 일반 (72)
        • 개발 인프라 (6)
      • 👨‍💻 프로젝트 경험 (6)
        • Work (0)
        • Toy (6)
      • ⚙️ 개발 팁 & 노하우 (21)
        • 프론트엔드 (6)
        • 기타 (15)
      • ☕️ 커리어 & 인터뷰 준비 (88)
        • 코딩 테스트 (88)
      • 📰 기술 트렌드 & 생각 정리 (4)
      • 📚 기타 (25)
        • 마케팅 (15)
        • 비개발서적 (10)
  • 블로그 메뉴

    • 태그
  • 링크

  • 공지사항

    • 모바일 접속 시 코드 하이라이팅 깨질 때
  • 인기 글

  • hELLO· Designed By정상우.v4.10.3
지식물원
#37 공식 명칭에는 상표를 붙이기
상단으로

티스토리툴바