AsChild 패턴 (Radix UI)

컴포넌트 기능은 유지하면서 렌더링 요소를 변경:

<Button asChild>
  <a href="/home">Link Button</a>
</Button>

핵심 구현 - Slot 컴포넌트:

const Slot = forwardRef(({ children, ...props }, ref) => {
  if (!isValidElement(children)) return null

  return cloneElement(children, {
    ...props,
    ...children.props,
    ref: ref || children.ref,
  })
})

자식 요소 타입에 따른 조건부 Props:

type ConditionalProps<T> = T extends ReactElement<any, 'a'>
  ? { href?: string; external?: boolean }
  : T extends ReactElement<any, 'button'>
  ? { type?: 'button' | 'submit' }
  : {}

// 사용
;<Anchor href="/home" external>
  {' '}
  {/* a 태그일 때만 href 허용 */}
  <a>Link</a>
</Anchor>

활용: 디자인 시스템, 라우터 통합 (<Button asChild><NextLink /></Button>)

#517