import { ComponentProps, ComponentPropsWithRef, ElementType, ForwardRefExoticComponent, ForwardRefRenderFunction, Fragment, ReactElement } from "react"; //#region src/utils/polymorphicForwardRef/index.d.ts /** * @description 유니온 타입에서 각각의 타입에 대해 `Omit`을 적용하는 타입입니다. * * `조건부 타입`을 사용하여 `분배 법칙`처럼 동작합니다. * * @template T - 분배 대상이 되는 유니온 타입 * @template K - 제거할 프로퍼티 키 * * @example * type Union = { a: string } | { b: number } * type Result = DistributiveOmit * * // 동작 원리와 순서 * // 1. Result = DistributiveOmit * // 2. Result = Omit<{ a: string }, 'a'> | Omit<{ b: number }, 'a'> * // 3. Result = {} | { b: number } */ type DistributiveOmit = T extends any ? Omit : never; /** * @description 두 타입을 병합하는 타입입니다. * * @template A - 첫 번째 타입 * @template B - 두 번째 타입 * * @example * type A = { a: string, b: number } * type B = { b: string, c: boolean } * type Result = Merge * * // 동작 원리와 순서 * // 1. Result = Merge * // 2. Result = Omit & B * // 3. Result = { a: string } & B * // 4. Result = { a: string, b: string, c: boolean } */ type Merge = Omit & B; /** * @description 유니온 타입의 각 구성 요소에 대해 `B` 타입과의 병합을 수행하는 타입입니다. * * 각 유니온 멤버에서 `B`의 키들을 제거한 후, `B` 타입과 병합합니다. * * @template A - 병합의 대상이 되는 유니온 타입 * @template B - 각 유니온 멤버와 병합될 타입 * * @example * type A = { a: string, c: boolean } | { b: number } * type B = { c: boolean } * type Result = DistributiveMerge * * // 동작 원리와 순서 * // 1. Result = (Omit<{ a: string, c: boolean }, "c"> | Omit<{ b: number }, 'c'>) & B; * // 2. Result = { a: string } & B | { b: number } & B; * // 3. Result = { a: string, c: boolean } | { b: number, c: boolean } */ type DistributiveMerge = DistributiveOmit & B; /** * @description 다형성 컴포넌트의 `props`의 타입을 정의하는 타입입니다. * * `as`를 포함해 고정 `props`와 지정된 요소 타입에 기본적으로 제공하는 `props`를 병합합니다. * * @template Component - 렌더링할 요소의 타입을 지정합니다. 예를 들어, 'button', 'div' 등 HTML 요소가 될 수 있습니다. * @template PermanentProps - 컴포넌트의 고정 `props` 타입입니다. * @template ComponentProps - 지정된 요소 타입에 기본적으로 제공하는 `props` 타입입니다. 예를 들어 button 요소의 경우 type, disabled 등이 있습니다. * * @example * interface ButtonProps { * variant: 'primary' | 'secondary'; * size: 'sm' | 'md' | 'lg'; * } * * // button 요소로 렌더링될 때의 타입 * type HtmlButtonProps = AsProps<'button', ButtonProps, ComponentProps<'button'>> * // HtmlButtonProps = { * // variant: 'primary' | 'secondary'; * // size: 'sm' | 'md' | 'lg'; * // as?: 'button'; * // ... 기타 button의 HTML 속성들 * // } */ type AsProps, ComponentProps extends Record> = DistributiveMerge; /** * @description `ref`를 포함한 다형성 컴포넌트의 함수 시그니처를 정의하는 타입입니다. * 하나의 컴포넌트가 여러 HTML 요소로 렌더링될 수 있도록 하며, 각 요소에 맞는 props와 ref를 자동으로 처리합니다. * * @template Default - 렌더링할 요소의 타입을 지정합니다. 예를 들어, 'button', 'div' 등 HTML 요소가 될 수 있습니다. * @template Props - 컴포넌트의 커스텀 `props` 타입입니다. * @template OnlyAs - 컴포넌트가 렌더링될 수 있는 요소 타입을 제한합니다. 예를 들어, 'button' | 'a' 를 넣으면 `as`로 'button' | 'a'만 넣을 수 있게 제한됩니다. */ type PolymorphicWithRef, OnlyAs extends ElementType = ElementType> = (props: AsProps : ComponentProps>) => ReactElement | null; /** * @description `React.forwardRef`를 사용한 다형성 컴포넌트의 전체 타입을 정의합니다. * `ForwardRefExoticComponent`와 `PolymorphicWithRef`를 결합합니다. * * @template Default - 렌더링할 요소의 타입을 지정합니다. 예를 들어, 'button', 'div' 등 HTML 요소가 될 수 있습니다. * @template Props - 컴포넌트의 커스텀 `props` 타입입니다. * @template OnlyAs - 컴포넌트가 렌더링될 수 있는 요소 타입을 제한합니다. 예를 들어, 'button' | 'a' 를 넣으면 `as`로 'button' | 'a'만 넣을 수 있게 제한됩니다. */ type PolyForwardComponent, OnlyAs extends ElementType = ElementType> = Merge : ComponentProps, Props & { as?: Default; }>>, PolymorphicWithRef>; /** * @description `React.forwardRef`를 위한 다형성 타입 래퍼입니다. * 컴포넌트에 다형성과 `ref` 전달 기능을 모두 부여합니다. * * @template Default - 렌더링할 요소의 타입을 지정합니다. 예를 들어, 'button', 'div' 등 HTML 요소가 될 수 있습니다. * @template Props - 컴포넌트의 커스텀 `props` 타입입니다. * @template OnlyAs - 컴포넌트가 렌더링될 수 있는 요소 타입을 제한합니다. 예를 들어, 'button' | 'a' 를 넣으면 `as`로 'button' | 'a'만 넣을 수 있게 제한됩니다. * * @returns 다형성과 `ref` 전달이 가능한 새로운 컴포넌트 타입을 반환합니다. */ type PolyRefFunction = , OnlyAs extends ElementType = ElementType>(Component: ForwardRefRenderFunction) => PolyForwardComponent; /** * @description `React.forwardRef`를 다형성 컴포넌트를 위한 타입으로 캐스팅하는 유틸리티입니다. * 기존의 `forwardRef`를 `PolyRefFunction` 타입으로 변환하여 다형성과 `ref` 전달을 모두 지원하는 컴포넌트를 생성할 수 있게 합니다. * * @example * // 기본 사용 * interface ButtonProps { * variant: 'primary' | 'secondary'; * size: 'sm' | 'md' | 'lg'; * } * * const Button = polymorphicForwardRef<'button', ButtonProps>((props, ref) => { * const Component = props.as ?? 'button'; * return ; * }); * * @example * // OnlyAs로 요소 타입 제한 * const Button = polymorphicForwardRef<'button', ButtonProps, 'button' | 'a'>((props, ref) => { * const Component = props.as ?? 'button'; * return ; * }); */ declare const polymorphicForwardRef: PolyRefFunction; //#endregion export { polymorphicForwardRef }; //# sourceMappingURL=index.d.ts.map