방구석에 놔둔 개발 노트

1년차 웹 / 앱 프론트엔드 엔지니어의 좌충우돌 얼렁뚱땅 앞뒤짱구 생존기

2024-07-03: TypeScript 유틸과 HTML 요소 상속

🤦 누구나 다 알던 간단한 지식인데 나는 이제 알게 된 내용들

4월에서 6월 사이에 면접 질문들을 준비하면서 이런저런 공부들을 하게 되었는데, 그 중에서 가장 충격적이었던 건 다른 사람은 다 알고 잘 쓰면서 정작 나는 모르던 것들이 있었다.

그 중 하나가 TypeScript의 유틸들과 HTML 요소의 속성들을 상속하는 방법이었다.

이걸 이제 알았다고 하니까 주변에서 물음표를 띄우던 사람들을 종종 봤는데, 이럴 때마다 내 지식이 한없이 비좁다라는 것이 느껴지곤 했다.

이번 글은 그 부끄러움에 대한 반성과 앞으로도 잘 쓰자라는 의미에서 작성하는 짧은 글이다. 이번 기회에 익혀두고 프로젝트에 적용해보도록 하자.

🧰 TypeScript의 Utility - Partial, Omit, Pick?

  • Partial

Partial은 특정 타입의 내용을 전부 optional하게 바꿔주는 타입이다.

아래와 같이 고정된 타입의 값에 undefined가 들어올 수 있도록 변경된다고 생각하자.

type Rank = {
    first : "tigers";
    second : "twins";
    third : "bears";
}

type NewRank = Partial<Rank>
// 위처럼 쓰면 타입이 아래와 같이 적용된다.
// type NewRank = {
//   first? : "tigers";
//   second? : "twins";
//   third? :"bears";
// }
  • Pick와 Omit

Pick은 특정 타입에서 특정 값만을 포함한 타입을 가리킨다.

Omit은 반대로 특정 타입에서 특정 값만을 제외한 타입을 가리킨다.

type PickRank = Pick<Rank, "first">
// 아래와 같이 된다.
// type PickRank = {
//   first: "tigers";
// }

type OmitRank = Omit<Rank, "first">
// 아래과 같이 된다.
// type OmitRank = {
//   second : "twins";
//   third : "bears";
// }

🎥 TypeScript의 Record

Recod는 객체의 데이터를 정의하는 타입이다.

객체에 어떠한 key나 value가 있을지는 모르지만, 이 key와 value의 타입이 Record로 지정한 타입만 들어올 수 있게 한다.

// 아래처럼 key와 value 모두 string으로 받아오는 타입이 있다고 하자.
type KBO = Record<string, string>

// 아래와 같이 지정해서 쓸 수 있다.
const RightRank:KBO = {
    first : "tigers",
    second : "twins",
    third : "bears"
}

// 아래는 지정한 Record의 객체 타입과 다르므로 에러가 발생한다.
const WrongRank:KBO = {
    1: "tigers",
    twins: 2,
    third: 3
}

이처럼 key와 value가 어떤 게 들어올지 지정하기 어려운 상태에서, Record를 이용하면 부담없이 객체의 데이터 타입을 결정할 수 있다.

❗ HTML 요소의 속성들을 Type으로 묶어 그대로 받아오는 방법?

React에서는 HTML 요소의 속성들을 Type으로 편하게 관리해주고 있다.

그래서 HTML 요소를 이용한 단일 컴포넌트를 만들 때, HTML 속성을 유지하면서도 다른 Props를 붙여서 반영해야한다면 아래와 같이 타입을 생성할 수 있다.

type InputPropType = InputHTMLAttributes<HTMLInputElement> & {
  errorCondition?: RegExp | boolean;
};

위처럼 Input의 속성들을 받아오면서 & 연산자를 이용해 타입을 확장하여 errorCondition을 받아오도록 했다.

이런 식으로 생성한 타입은 아래와 같이 이용할 수 있다.

export default function Input (props:InputPropType) {
    return (<StInput {...props} />)
}

HTML 요소를 그대로 props에서 가져오는 상황에서 HTML 요소의 속성에 해당하지 않는 친구를 따로 이용해야 할 경우, props를 쪼갤 수 밖에 없는 상황이 온다.

그 경우에는 따로 받을 부분만 구조 전개 구문을 통해 받아온 뒤, 나머지는 rest 연산자를 통해서 붙여주면 특정 Props를 제외하고 나머지 속성을 그대로 붙여줄 수 있다.

export default function Input (props:InputPropType) {
    const {errorCondition, ...rest} = props;
    return (<StInput $errorCondition={errorCondition} {...rests} />)
}

이렇게 용도에 알맞게 자신이 사용하고자 하는 타입들을 적용해서 HTML 요소에 적용할 수 있다.

🔖 참고 자료

Documentation - Utility Types

Documentation - Utility Types

Documentation - Utility Types

Documentation - Utility Types

HTMLAttributes | typescript