从 React 组件中导出 TypeScript 类型的字符串属性值?
Posted
技术标签:
【中文标题】从 React 组件中导出 TypeScript 类型的字符串属性值?【英文标题】:Export TypeScript typed string prop values from a React component? 【发布时间】:2020-09-11 22:52:40 【问题描述】:我有一个 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>
)
【问题讨论】:
你绝对可以做这样的事情。看看这个答案 - ***.com/a/43101184/13058340 【参考方案1】:在 TypeScript 中,您可以从值中获取类型(使用 typeof
),但您永远无法从类型中获取值。所以如果你想消除重复,你需要使用一个值作为你的真实来源,并从中派生出类型。
例如,如果您将按钮类型数组作为事实来源,那么您可以使用const assertion (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>
);
【讨论】:
【参考方案2】:您可以生成声明对象并从中声明类型。这样,您将能够遍历其键,并且每次更改时类型都是最新的。
Button.tsx
import * as React from "react";
export const ButtonSkins =
primary: "primary",
secondary: "secondary",
tertiary: "tertiary"
;
export type ButtonSkin = keyof typeof ButtonSkins;
export type ButtonProps =
skin: ButtonSkin;
;
export const Button: React.FC<ButtonProps> = ( skin ) => (
<button className=skin>skin</button>
);
App.tsx(我把循环放在这里,但你当然可以在故事书中使用它)
import * as React from "react";
import render from "react-dom";
import Button, ButtonSkins, ButtonSkin from "./Button";
const App = () => (
<div>
(Object.keys(ButtonSkins) as Array<ButtonSkin>).map(skin =>
return <Button skin=skin />;
)
<h2>Start editing to see some magic happen "\u2728"</h2>
</div>
);
render(<App />, document.getElementById("root"));
https://codesandbox.io/s/recursing-browser-qkgzb?file=/src/index.tsx
【讨论】:
以上是关于从 React 组件中导出 TypeScript 类型的字符串属性值?的主要内容,如果未能解决你的问题,请参考以下文章
在 React TypeScript 组件中导入 Javascript
React Redux Firebase - 您可能忘记从定义组件的文件中导出组件,或者您可能混淆了默认导入和命名导入
在 react-typescript 中导入 html 文件
您可能忘记从其定义的文件中导出组件,或者您可能混淆了默认导入和命名导入