我有一个功能组件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
答案 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问题类似,但是我无法使其正常工作,如果有更新,它将发布。