Practicing Typescript: Polymorphic components

zenoan·2021년 12월 22일
0

typescript

목록 보기
11/11

Polymorphic components

  • Use polymorphic components to build a design system or component library
// Text.tsx
// The underlying problem of this is that div tag never changes
import React from 'react'

type TextProps = {
  size?: 'sm' | 'md' | 'lg'
  color?: 'primary' | 'secondary'
  children: React.ReactNode
}
export const Text = ({size, color, children}) => {
	return <div className={`class-with-${size}-${color}`}>{children}</div>
}
// Text.tsx
// Use generic type E and extend React Element type for html tag
import React from 'react'

type TextOwnProps<E extends React.ElementType> = {
  size?: 'sm' | 'md' | 'lg'
  color?: 'primary' | 'secondary'
  children: React.ReactNode
  as?: E
}
// React component props with genereric type: to know what is the html 
// element whose props need to be combined with TextOwnProps.
// With only = TextOwnProps<E> & React.ComponentProps<E>,
// name collision and duplicate types can occur Ex) children with div children
// With omit keyof TextOwnProps<E> can omit the TextOwnProps type we have created
type TextProps<E extends React.ElementType> = TextOwnProps<E> &
  Omit<React.ComponentProps<E>, keyof TextOwnProps<E>>

// default element : div
export const Text = <E extends React.ElementType = 'div'>({
  size,
  color,
  children,
  as
}: TextProps<E>) => {
  const Component = as || 'div'
  return (
    <Component className={`class-with-${size}-${color}`}>{children}</Component>
  )
}
// App.tsx
import React from 'react;
import { Text } from './components/polymorphic/Text'

function App() {
	return (
    	<div className='App'>
        	<Text size='lg' as='h1'>
              Heading
            </Text>
            <Text size='md' as='p'>
              Paragraph
            </Text>
            <Text size='sm' color='secondary' as='label' htmlFor='someId'>
              Label
            </Text>
         </div>
    )
}
profile
프론트엔드 개발자

0개의 댓글