typescript - 从 React 组件中导出 TypeScript 类型的字符串属性值?
问题描述
我有一个 React / TypeScript 组件。在 Button.tsx 中:
type Props = {
type:
| "primary"
| "secondary"
| "tertiary"
}
const Button = React.FC<Props> = ({ type }) => {
const color = (() => {
switch (type) {
case "primary":
return 'red';
case "secondary":
return 'blue';
case "tertiary":
return 'green';
default:
throw new Error("A backgroundColor condition was missed");
}
})();
return(
<button style={{ background: color }}>Im a button</button>
)
}
我可以在其他组件中使用它。在 Page.tsx 中:
const Page = () => {
return(
<div>
<h1>Heading</h1>
<Button type="primary" />
</div>
)
}
在 Storybook 中,我需要使用所有类型值。在 Button.stories.js 中:
const types = [
"primary",
"secondary",
"tertiary",
];
export const AllButtons = () => {
return(
types.map(type=>{
<Button type={type} key={type} />
})
)
}
不必重复“主要”、“次要”、“第三级”,有没有办法可以从 Button.tsx 导出它们?这样,如果添加了新类型,Storybook 文件将自动拥有它。
我可以在 Button.tsx 中使用枚举:
export enum Types {
primary = "primary",
secondary = "secondary",
tertiary = "tertiary",
}
type Props = {
type: Types;
};
但是,使用 Button 的组件不能只传递一个字符串,每次使用 Button 时都必须导入枚举,这是不值得的。在 Page.tsx 中:
import { Type } from './Button'
const Page = () => {
return(
<div>
<h1>Heading</h1>
<Button type={Type.primary} />
</div>
)
}
解决方案
在 TypeScript 中,您可以从值中获取类型(使用typeof
),但永远无法从类型中获取值。所以如果你想消除重复,你需要使用一个值作为你的真实来源,并从中派生出类型。
例如,如果您将按钮类型数组作为事实来源,那么您可以使用const 断言( as const
) 从中派生类型:
// Button.tsx
export const BUTTON_TYPES = [
"primary",
"secondary",
"tertiary",
] as const;
type Types = typeof BUTTON_TYPES[number];
type Props = {
type: Types;
}
const Button: React.FC<Props> = ({ type }) => {
// ...
return(
<button style={{ background: color }}>Im a button</button>
)
}
然后您可以导入BUTTON_TYPES
您的故事并对其进行迭代。
您还可以制作从按钮类型到颜色的映射,并将其用作您的真实来源。这将使您color
从组件中消除该功能:
const TYPE_TO_COLOR = {
primary: 'red',
secondary: 'blue',
tertiary: 'green',
} as const;
type Types = keyof typeof TYPE_TO_COLOR;
// type Types = "primary" | "secondary" | "tertiary"
export const BUTTON_TYPES = Object.keys(TYPE_TO_COLOR);
type Props = {
type: Types;
}
const Button: React.FC<Props> = ({ type }) => {
const color = TYPE_TO_COLOR[type];
if (!color) {
throw new Error("A backgroundColor condition was missed");
}
return (
<button style={{ background: color }}>Im a button</button>
);
}
推荐阅读
- scala - Scalatest:组合断言
- ios - 如何在 iOS Web 应用程序中保存凭据/会话?
- python - 是否可以在单个 GRPC 服务器上运行同一服务的多个实例?
- html - 在html中居中文本,同时保持左对齐?
- transactions - 转换为 .net core 3.1 后,当前的 TransactionScope 已完成错误
- file - 在 go 中逐字节处理文件
- mysql - MySQL 使用 WHERE 的结果更新条件(已解决)
- r - 删除重复项,同时优先考虑 R 中不同列中的特定值
- javascript - 在 React Native 中使用异步组件的 Redux
- python - 为什么 numpy ifft 不返回我的原始光谱?