如何在TypeScript中通过组件注入将defaultProps添加到通用功能组件?

时间:2019-09-26 20:09:26

标签: reactjs typescript typescript-generics

我有一个功能组件Button,它需要一个道具as来注入HTML元素或其他组件。我想将as的{​​{1}}属性默认为Link的{​​{1}}组件。这将使react-router的{​​{1}}属性成为Link的强制属性。因此,在编写to时应该出现错误,但是编译器没有报告错误。

我正在使用Button中的以下设置的打字稿v3.5.3:

<Button>Press me!</Button>

这是我目前的情况(简体),tsconfig.json es6样式默认为{ "compilerOptions": { "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitThis": true, "strictFunctionTypes": true, "strictBindCallApply": true, "alwaysStrict": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true } }

Link

因此,鉴于以上所述,这是结果和期望:

as

如何使第一个失败?

解决以下问题也很酷。与import React from 'react' import { Link } from 'react-router-dom' interface ButtonProps { children?: string } type ElementInjector<T extends React.ElementType> = { as: T } & React.ComponentPropsWithoutRef<T> export const Button = <T extends React.ElementType>({ as: Tag = Link, ...props }: ButtonProps & ElementInjector<T>) => { return <Tag {...props} /> } 无关,但与通用方法有关。

<Button>Button</Button>            // error   - asking for `as` not `to`
<Button as={Link}>Button</Button>  // error   - ok
<Button to="/">Button</Button>     // error   - asking for `as`
<Button as="a">Button</Button>     // success - ok

Example to play with

1 个答案:

答案 0 :(得分:1)

在将类型参数推断给组件时,将不考虑参数默认值。由于没有其他地方可以使用T,因此它将默认为unknown。解决方案是为T

添加默认类型

export const Button = <T extends React.ElementType = typeof Link>({
    tag: Tag = Link,
    ...props
  }: ButtonProps & ElementInjector<T>) => {
    return <Tag {...props} />
  }

let x = <Button>Button</Button>                      // error expected
let x1 = <Button tag={Link}>Button</Button>          // error   - ok
let x2 = <Button to="/">Button</Button>              // success - ok
let x3 = <Button tag="a">Button</Button>             // success - ok

关于您的第二个问题,它与this问题类似,但是我无法使其正常工作,如果有更新,它将发布。