TypeScript 和 React 中的联合类型 props

bor*_*cle 1 typescript reactjs

我有一个带有 prop 的组件,我想将其限制为一系列字符串,因此我使用联合类型,如下所示:

type HeadingProps = {
    level?: 'h1' | 'h2' | 'h3' | 'h4'| 'h5' | 'h6'
}

const Heading: React.FC<HeadingProps> = ({children, level = 'h2'}) => {
    return <Box as={level} />
}
Run Code Online (Sandbox Code Playgroud)

当我这样使用时效果很好..

<Heading level="h1">Hello, world!</Heading>
Run Code Online (Sandbox Code Playgroud)

但如果我尝试将它与数组一起使用,则会收到错误:

{['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].map((level: string) => (
    <Heading level={level}>{level}</Heading>
)}
Run Code Online (Sandbox Code Playgroud)

类型“string”不可分配给类型“h1”| “h2”| “h3”| “h4”| “h5”| “h6”| 未定义'.ts(2322)

如何获得 prop 的类型,以便只有这些字符串有效,但在像上面这样的数组中使用组件时能够传递有效的字符串值?

编辑 这就是当前类型的样子:

export const HeadingLevels = {
  h1: `h1`,
  h2: `h2`,
  h3: `h3`,
  h4: `h4`,
  h5: `h5`,
  h6: `h6`,
}
export type Level = keyof typeof HeadingLevels
type HeadingProps = BoxProps & {
  level?: Level
}
Run Code Online (Sandbox Code Playgroud)

jca*_*alz 5

['h1', 'h2', 'h3', 'h4', 'h5', 'h6']被编译器推断为类型,string[]因为通常这是正确的做法,如

const arr = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']; // inferred as string[]
arr.push("h7"); // okay
Run Code Online (Sandbox Code Playgroud)

但在您的情况下,您希望编译器知道该数组的内容始终是(只要您使用它)您设置的特定字符串文字

从 TypeScript 3.4 开始,处理此问题的最简单方法是使用断言const告诉编译器您的数组旨在成为您正在从中读取特定字符串文字的内容:

(['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] as const).map((level) => (
    <Heading level={level}>{level}</Heading>
))
Run Code Online (Sandbox Code Playgroud)

这应该可以正常工作,不会出现错误。请注意,我从 中删除了类型注释level。您不想扩大levelstring,因为那样编译器就无法再确定它是否合适。相反,让编译器推断 的类型level,它将"h1"|"h2"|...|"h6"根据需要将其作为您的 union 执行。

好的,希望有帮助;祝你好运!

链接到代码