TypeScript
emotion-variants 已经能从配置中推断 variant 类型。本页介绍如何从 ev() 结果推导出 React 组件的 props,让组件的 props 类型与样式保持同步。
VariantProps 类型
emotion-variants 导出了 VariantProps。把任意 ev() 结果的类型传给它,就能得到对应的 variants:
import { ev, type VariantProps } from 'emotion-variants';
const button = ev({
variants: {
size: {
small: {},
medium: {},
large: {},
},
color: {
primary: {},
danger: {},
},
},
});
type ButtonVariants = VariantProps<typeof button>;
// { size?: 'small' | 'medium' | 'large'; color?: 'primary' | 'danger' }在 variants.size 中新增一个值,ButtonVariants['size'] 会自动更新。
与 HTML 元素 props 结合
对于类似按钮的多态组件,与 ComponentPropsWithoutRef 取交叉类型:
import type { ComponentPropsWithoutRef } from 'react';
export type ButtonProps = ComponentPropsWithoutRef<'button'> & ButtonVariants;
export function Button({ size, color, ...rest }: ButtonProps) {
return <button css={button({ size, color })} {...rest} />;
}搭配合理的默认值
默认值只在 defaultVariants 中声明一次,props 原样透传即可。省略的 prop 会以 undefined 传入,并仍然解析为默认值;如果在 prop 边界再设一套默认值,只会让两者有机会产生分歧:
const button = ev({
variants: {
/* ... */
},
defaultVariants: {
size: 'medium',
color: 'primary',
},
});
export function Button({ size, color, ...rest }: ButtonProps) {
return <button css={button({ size, color })} {...rest} />;
}解析规则请参阅 Default Variants。
转发 ref
import { forwardRef, type ComponentPropsWithoutRef } from 'react';
export type ButtonProps = ComponentPropsWithoutRef<'button'> & ButtonVariants;
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ size, color, ...rest }, ref) => (
<button ref={ref} css={button({ size, color })} {...rest} />
),
);只提取部分维度
如果只想把部分维度作为 props 暴露(例如对公开 API 隐藏 density),用 Pick 即可:
type PublicButtonProps =
ComponentPropsWithoutRef<'button'> &
Pick<ButtonVariants, 'size' | 'color'>;从设计系统中重新导出
如果你维护的设计系统包在内部使用 emotion-variants,请导出 props 类型,这样使用方就不必导入内部的样式文件:
// design-system/src/button/index.ts
export { Button } from './button';
export type { ButtonProps } from './button';使用方从你的包中导入 ButtonProps,完全不需要接触底层的 ev() 配置。
另请参阅
在 GitHub 上编辑此页
最后更新于