Skip to main content

타입스크립트와 리엑트

· 3 min read

프록시 컴포넌트 작성하기

Q. 표준 HTML 컴포넌트를 많이 사용하는데, 이때 필요한 모든 프로퍼티를 항상 설정하는 작업이 번거로움 A. 프록시 컴포넌트를 만들고 적용한다.

ㅅㄷㄴㅅ

특정 속성 재정의 못하게 하기

type SubmitButtonProps = Omit<JSX.IntrinsicElements["button"], "type">;

function SubmitButton(props: SubmitButtonProps) {
return <button type="submit" {...props} />;
}
type StyleButton = Omit<
JSX.IntrinsicElements["button"],
"type" | "className" | "style"
> & { type: "primary" | "secondary" };

function StyledButton({ type, ...allProps }: StyledButton) {
return <Button type="button" className={`btn-${type}`} {...allProps} />;
}

특정 속성만 필수 값으로 정의하기

type MakeRequired<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
type ImgProps = MakeRequired<JSX.IntrinsicElements["img"], "alt" | "src">;

export function Img(prps: ImgProps) {
return <img {...props} />;
}

const anImage = <Img />;
// alt, src 속성만 필수여서 ts 에러가 남

제어 컴포넌트 구현하기

Q. 입력과 같은 form 요소의 상태를 브라우저와 리엑트 중 어디에서 관리할지 결정해야 하므로 상화이 복잡해짐 A. 런타임에 ㅣㅂ제어와 제어로 전환되지 않도록 구별된 유니온과 선택형 never 기법을 사용하는 프록시 컴포넌트를 구현

import React, { useState } from "react";

type OnlyRequired<T, K extends keyof T = keyof T> = Required<Pick<T, K>> &
Partial<Omit<T, K>>;

type ControlledProps = OnlyRequired<
JSX.IntrinsicElements["input"],
"value" | "onChange"
> & {
defaultValue?: never;
};

type UnControlledProps = OnlyRequired<
JSX.IntrinsicElements["input"],
"value" | "onChange"
> & {
defaultValue: string;
value?: never;
onChange?: never;
};

type InputProps = ControlledProps | UnControlledProps;

function Input({ ...allProps }: InputProps) {
return <input {...allProps} />;
}

function Controlled() {
const [val, setVal] = useState("");
return <Input value={val} onChange={(el) => setVal(e.target.value)} />;
}

function UnControlled() {
return <Input defaultValue="Hello" />;
}

사용자 정의 훅 형식 정의하기

Q. 커스텀 훅을 정의하고 적절한 형식을 얻으려 한다. A. 튜플 형식이나 const 컨텍스트를 사용한다.

export const useToggle = (initialValue: boolean) => {
const [value, setValue] = useState(initialValue);
const toggleValue = () => setValue(!value);
return [value, toggleValue] as const;
};

리엑트의 합성 이벤트 시스템에서 콜백 형식화하기

import React from "react";

type WithChildren<T = {}> = T & { children?: React.ReactNode };

type ButtonProps = {
onClick: (event: React.MouseEvent) => void;
} & WithChildren;

function Button({ onClick, children }: ButtonProps) {
return <button onClick={onClick}></button>;
}