[英]Typescript isn't complaining when a React Functional Component (React.FC<Props>) with wrong props is send as a prop?
I am trying to send a functional component with some props to another component and in the receiving component trying to type check that component for some of the props.我正在尝试将带有一些道具的功能组件发送到另一个组件,并在接收组件中尝试键入检查该组件的某些道具。 Here is the code:
这是代码:
// BaseButton.tsx
export type ButtonProps = {
label: string
size?: 'sm' | 'md' | 'lg' | 'normal'
icon?: React.FC<{ size?: number; foo: string }>
} & React.ButtonHTMLAttributes<HTMLButtonElement
export const BaseButton: React.FC<ButtonProps> = props => {/* ...return the button component */}
// Icon.tsx
type Props = {
style?: React.CSSProperties
size?: number
}
export const Icon: React.FC<Props> = ({ style, size = 24 }) => {/* ... return Icon component */}
// where I render the component
<BaseButton icon={Icon} label="Sign in" />
// ^^^ I am expecting Typescript to complain
Since the icon?: React.FC<{ size?: number; foo: string }>
自
icon?: React.FC<{ size?: number; foo: string }>
icon?: React.FC<{ size?: number; foo: string }>
in ButtonProps
has an extra prop foo
I am expecting Typescript to complain about it. icon?: React.FC<{ size?: number; foo: string }>
in ButtonProps
有一个额外的道具foo
我期待 Typescript 抱怨它。 But it is not.但事实并非如此。
This will throw an error while trying to invoke it with JSX syntax:这将在尝试使用 JSX 语法调用它时引发错误:
icon?: React.FC<{ size?: number; foo: string }>
const {icon: Icon} = props
<Icon />
Instead, the type should be:相反,类型应该是:
icon?: React.ComponentType<{ bar: number }>
Basically, you can assign functions with fewer parameters to functions with more parameters :基本上,您可以将具有较少参数的函数分配给具有更多参数的函数:
let fn1 = (props: { size: number }) => 42
let fn2 = (props: { size: number; foo: string }) => 42
fn2 = fn1 // this works
fn1 = fn2 // error
Or in other words:或者换句话说:
With a variable let fn2
and type (props: { size: number; foo: string }) => number
given, a client needs to call it with two props size
and foo
.使用变量
let fn2
和类型(props: { size: number; foo: string }) => number
given,客户端需要使用两个 props size
和foo
调用它。 We now can assign fn2 = fn1
, as it is OK for the underlying implementation fn1
to ignore some of the input props and only deal with size
.我们现在可以分配
fn2 = fn1
,因为底层实现fn1
可以忽略一些输入道具并且只处理size
。
Carried over to your case:转移到您的案例中:
Icon
with type React.FC<{ style?: React.CSSProperties; size?: number}>
类型为
React.FC<{ style?: React.CSSProperties; size?: number}>
的Icon
React.FC<{ style?: React.CSSProperties; size?: number}>
is assignable to the ButtonProps
icon property with type React.FC<{ size?: number; foo: string }>
React.FC<{ style?: React.CSSProperties; size?: number}>
可分配给类型为React.FC<{ size?: number; foo: string }>
的ButtonProps
图标属性React.FC<{ size?: number; foo: string }>
. React.FC<{ size?: number; foo: string }>
。
let fc1: React.FC<{
style?: React.CSSProperties
size?: number
}> = // ...
let fc2: React.FC<{ size?: number; foo: string }> = // ...
fc2 = fc1 // works
fc1 = fc2 // error
The type FunctionComponent
has function type definition, so you can pass either a React component or a function to be invoked later. FunctionComponent
类型具有 function 类型定义,因此您可以传递 React 组件或 function 以供稍后调用。
type FC<P = {}> = FunctionComponent<P>;
interface FunctionComponent<P = {}> {
(props: PropsWithChildren<P>, context?: any): ReactElement | null; <--- Here
propTypes?: WeakValidationMap<P>;
contextTypes?: ValidationMap<any>;
defaultProps?: Partial<P>;
displayName?: string;
}
Here's a sandbox with an example of invoking the props.icon
component from the BaseButton component.这是一个沙箱,其中包含从 BaseButton 组件调用
props.icon
组件的示例。 You'll see how the props foo
and size
must be passed when calling the function on line 21.您将看到在第 21 行调用 function 时必须如何传递道具
foo
和size
。
https://codesandbox.io/s/trusting-banach-prwos?file=/src/App.tsx https://codesandbox.io/s/trusting-banach-prwos?file=/src/App.tsx
https://www.typescriptlang.org/docs/handbook/interfaces.html#function-types https://www.typescriptlang.org/docs/handbook/interfaces.html#function-types
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.