고급 TypeScript에 대한 참고 사항: 유형 변환

14593 단어 typestypescriptreact

소개



이 노트는 고급TypeScript 항목을 더 잘 이해하는 데 도움이 되며 특정 상황에서 TypeScript를 활용하는 방법을 조회해야 할 때 도움이 될 수 있습니다. 모든 예제는 TypeScript 4.6을 기반으로 합니다.

변형 유형



정의된 유형이 있지만 특정 사용 사례에 대해 작동하도록 일부 속성을 조정해야 하는 상황이 있습니다. Box 유형을 정의한 다음 예를 살펴보겠습니다.

type Vec2 = { x: number; y: number };
type Box = {
    id: string;
    size: Vec2;
    location: Vec2;
    content: string;
    color: string;
};


Box 유형은 사용자가 크기, 내용, 색상 및 위치를 정의할 수 있는 사용자 인터페이스가 있다는 점을 제외하면 잘 작동합니다. id 속성이 아직 정의되지 않아 유형을 그대로 사용할 수 없습니다. 제공된 값이 Box 속성이 선택 사항인 id임을 입력에 알릴 방법이 필요합니다.
다음 예제는 작동하지 않습니다.

const defineBox = (box: Box) => {
   // some processing happening here
};
defineBox({
  content: "Content goes here",
  color: "green",
  location: {x: 100, y: 100},
  size: {x: 50, y: 50}
}); 
/** 
 * Fail: Property 'id' is missing in type 
 * '{ content: string; color: string; location: { x: number; 
 * . y: number; }; size: { x: number; y: number; }; }' 
 * but required in type 'Box'. 
 */


TypeScript는 id 속성이 Box 형식에 필요하다고 불평합니다. 좋은 소식은 우리 자신의 Box 유형을 정의하여 작동하도록 MakeOptional 유형을 변환할 수 있다는 것입니다. 기본 제공 유형PickOmit를 활용하여 선택 사항으로 변환할 수 있는 정의된 키를 허용하는 유형을 만들 수 있습니다.

type MakeOptional<Type, Keys extends keyof Type> = 
  Omit<Type, Keys> & Pick<Partial<Type>, Keys>;


무슨 일이 일어나고 있는지 자세히 살펴 보겠습니다. 먼저 Omit를 사용하여 원래 유형에서 키를 제거한 다음 Partial 유형을 통해 유형을 부분적으로 만들고 이전에 제외된 키를 선택합니다. 두 가지 유형 작업을 결합하여 이제 이전 예제에서 새로 생성된MakeOptional을 사용할 수 있습니다.

type BoxIdOptional = MakeOptional<Box, "id">;
const defineBox = (box: BoxIdOptional) => {

};
defineBox({
  content: "Content goes here",
  color: "green",
  location: {x: 100, y: 100},
  size: {x: 50, y: 50}
});


우리의 defineBox 함수는 id가 제공되는지 여부에 관계없이 이제 예상대로 작동합니다. 이것은 이미 훌륭하지만 필요에 따라 더 많은 유형 변환을 수행할 수 있습니다. 몇 가지 시나리오를 더 살펴보겠습니다.
예를 들어 string 유형의 모든 속성을 number 유형으로 변환하려고 합니다. 이는 자체ConvertTypeTo 유형을 정의하여 달성할 수 있습니다.

type ConvertTypeTo<Type, From, To> = {
  [Key in keyof Type]: Required<Type>[Key] extends From ? To : Type[Key];
};


모든 키를 검토하여 키가 From 제네릭 유형을 확장하고 정의된 To 유형으로 변환하는지 확인합니다.

/**
 * type BoxStringToNumber = {
 *   id: number;
 *   size: Vec2;
 *   location: Vec2;
 *   content: number;
 *   color: number;
 * }
 */
type BoxStringToNumber = ConvertTypeTo<Box, string, number>;

ConvertTypeTo 유형을 사용하여 string 유형의 모든 속성을 number 로 변환했습니다.
또 다른 시나리오는 유형별로 속성을 포함하거나 제외하려는 경우일 수 있습니다. 여기서 유형을 기반으로 속성 키를 추출할 수 있는 빌딩 블록 유형을 작성할 수 있습니다.

type FilterByType<Type, ConvertibleType> = {
  [Key in keyof Required<Type>]: Required<Type>[Key] extends ConvertibleType ? Key : never;
}[keyof Type];


다시, 주어진 유형의 모든 키를 반복하고 키가 필터링하려는 유형을 확장하는지 확인합니다. convertibleType를 확장하지 않는 키는 never를 반환하여 필터링됩니다.
이전에 정의한 FilterByType를 사용한 짧은 Box 테스트는 string 유형의 모든 키를 검색할 수 있음을 보여줍니다.

// type BoxFilteredByTypeString = "id" | "content" | "color"
type BoxFilteredByTypeString = FilterByType<Box, string>;


이제 FilterByType가 준비되었으므로 유형별로 속성을 포함하거나 제외하는 사용자 정의 유형을 작성할 수 있습니다. 제외하려면 Omit를 다시 사용하고 이를 사용자 정의 유형과 결합할 수 있습니다.

type MakeExcludeByType<Type, ConvertibleType> = 
  Omit<Type, FilterByType<Type, ConvertibleType>>;


유형별로 모든 속성을 포함하려면 OmitPick로 바꾸기만 하면 됩니다.

type MakeIncludeByType<Type, ConvertibleType> = 
  Pick<Type, FilterByType<Type, ConvertibleType>>;


다음은 문자열 유형의 모든 속성을 포함하거나 제외하여 Box 유형을 변환하는 방법을 보여주는 예입니다.

/**
  type BoxOnlyVec2 = {
    size: Vec2;
    location: Vec2;
  }
 */
type BoxOnlyVec2 = MakeExcludeByType<Box, string>;

/**
  type BoxOnlyNumber = {
    id: string;
    content: string;
    color: string;
  }
 */
type BoxOnlyNumber = MakeIncludeByType<Box, string>;


예를 들어 속성을 필수, 선택 또는 유형에 따라 읽기 전용으로 만드는 것과 같이 우리가 할 수 있는 더 많은 변환이 있습니다. Here are more examples you can checkout

이제 유형을 변환하는 방법에 대한 기본 아이디어가 있어야 합니다.


질문이나 피드백이 있는 경우 여기에 의견을 남기거나 Twitter를 통해 연결하십시오.

좋은 웹페이지 즐겨찾기