React TypeScript 기능 구성 요소의 조건부 속성

패턴 설명



속성은 다른 속성에 특정 값이 있는 경우에만 존재해야 합니다.

예제 문제



예를 들어: 구성 요소에 대한 세 가지 가능한 작업(다운로드, 미리보기 및 인쇄)을 원하고 클릭 이벤트인 버튼이 해당 작업을 실행하도록 하고 싶다고 가정해 보겠습니다. 작업은 다음과 같이 그룹화되며 구성 요소를 통해 사용자가 PDF를 미리 보고 인쇄하거나 PDF를 다운로드할 수 있습니다.

메서드를 선택 사항으로 만들고 런타임에 자격을 얻을 수 있지만 이것은 TypeScript의 목적을 무효화합니다. 다음과 같은 것:

interface ActionComponent {
    className:string,
    ... // other properties go here
    purpose:"print" | "download",
    onDownload?:()=>void,
    onPreview?:()=>void,
    onPrint?:()=>void,
}


그런 다음 코드에서 다음과 같이 이벤트를 연결할 수 있습니다.

 return (
     {props.purpose === "download" && ( 
         <button onClick={props.onDownload!}>
         </button>
     )}
     {props.purpose === "print" && (
         // render print buttons wired to with props.onPreview and props.Print 
     )})


여기에서 우리는 ! TypeScript가 선택적props.onDownload 메서드를 사용하여 컴파일하도록 하려면 인쇄 버튼에 대해서도 동일한 작업을 수행해야 하며 속성이 채워진다고 가정합니다. 상위 구성 요소에서 목적 속성을 "다운로드"로 설정하고 onDownload 속성을 채우지 않아 TypeScript가 방지하도록 설계된 런타임 오류 유형을 정확히 생성할 수 있습니다. props.onDownload가 채워진 경우 삼항 연산자를 사용하여 검증하고 런타임에 부재를 처리하여 다시 TypeScript 사용 목적을 무효화하는 것과 같이 피할 수 있는 문제를 일으키는 다른 접근 방식도 있습니다.

해결책



TypeScript를 사용하면 사용자 정의 유형과 식별 조합을 사용하여 조건부 속성을 만들 수 있습니다. 구성 요소의 공통 속성을 사용하여 인터페이스 만들기

interface BaseProps {
    className:string,
    ... // other properties go here
}


이제 식별 조합에서 유형을 생성합니다. 진행하면서 이것이 어떻게 작동하는지 설명하겠습니다.

type PdfButtonProps = 
| {
    purpose: "download",
    onDownload:()=>void,
} | {
    purpose: "print",
    onPreview:()=>void,
    onPrint:()=>void,
}


PdfButtonProps의 유형은 두 유형 간의 식별 조합에 의해 결정됩니다. 차별은 purpose 인 공유 재산에서 발생합니다. 삼항 연산자의 관점에서 생각할 수 있으며 다음과 같습니다.

const pdfButton = purpose === "download" ? new PdfDownloadButton() : new PdfPrintButtons();


기능 구성 요소를 선언할 때 BaseProps 인터페이스와 PdfButtonProps 유형의 교차로 새 유형을 만들고 이를 기능 구성 요소 props로 사용할 수 있습니다(기능 구성 요소 선언에 대한 선호하는 접근 방식에 맞게 변경).

type PdfComponentProps = BaseProps & PdfButtonProps;

const PdfComponent: React.FC<PdfComponentProps> = (props) => {
    ...
    return (
        ...// other possible components
        {props.purpose === "download" && (
            // render download button wired with props.onDownload
        )}
        {props.purpose === "print" && (
            // render print buttons wired with props methods
        )}
    )
}


상위 구성 요소의 코드에서:

<div>
    <PdfComponent 
        className="form-buttons-pdf"
        purpose="download"
        onDownload={onDownloadHandler} /> // Compiles!

    <PdfComponent
        className="form-buttons-pdf"
        purpose="download"
        onPreview={onPreviewHandler}
        onPrint={onPrintHandler} /> // Does not compile
</div> 


첫 번째 인스턴스는 컴파일되지만 PdfComponent의 두 번째 인스턴스가 컴파일되지 않는 이유는 purpose === "download"가 있는 PdfButtonProps 유형에 onPreview 또는 onPrint 속성이 없고 코드가 onDownload 속성을 제공하지 않기 때문입니다. 첫 번째 인스턴스의 목적이 "인쇄"로 설정된 경우 해당 유형에 대한 onDownload 속성이 없고 onPrint 및 onPreview 속성이 제공되지 않았기 때문에 컴파일되지 않습니다.

추가 읽기



TypeScript Conditional Types

TypeScript Union and Intersections

좋은 웹페이지 즐겨찾기