Reactjs TypeScript允许函数作为与函数签名的in-param冲突的React prop?
为什么TypeScript类型检查器允许带有与定义不完全匹配的函数参数的道具 具体来说,我定义了一个函数Reactjs TypeScript允许函数作为与函数签名的in-param冲突的React prop?,reactjs,typescript,Reactjs,Typescript,为什么TypeScript类型检查器允许带有与定义不完全匹配的函数参数的道具 具体来说,我定义了一个函数callbackImpl=(str:string):number,并将其作为React prop参数提供,该参数定义为callback(parameter:string | undefined):number,这令人惊讶地有效 这对我来说是不直观的,在我看来是相当危险的 但是!调用callbackImpl(未定义)不起作用,我认为这是正确的 一个完整的例子: import React from
callbackImpl=(str:string):number
,并将其作为React prop参数提供,该参数定义为callback(parameter:string | undefined):number代码>,这令人惊讶地有效
这对我来说是不直观的,在我看来是相当危险的
但是!调用callbackImpl(未定义)
不起作用,我认为这是正确的
一个完整的例子:
import React from "react";
interface Props {
callback(parameter: string | undefined): number;
}
class A extends React.Component<Props> {
componentDidUpdate() {
this.props.callback(undefined);
}
}
class B extends React.Component {
private callbackImpl = (str: string): number => {
// Will crash if str is undefined
return str.length;
};
// THIS IS NOT ALLOWED! And rightly so!
private callLocalWithUndefined() {
// TS2345: Argument of type 'undefined' is not assignable to parameter of type 'string'.
this.callbackImpl(undefined);
}
render() {
return (
<React.Fragment>
<A
// This is obviously just as illegal as what happens in callLocalWithUndefined,
// since callbackImpl explicitly does not accept undefined as the first parameter,
// but no type errors here!?
callback={this.callbackImpl}
/>
</React.Fragment>
);
}
}
我做错什么了吗?我的tsconfig设置是否错误?我是不是误解了什么
谢谢
编辑
Titian Cernicova Dragomir回答后的其他资源
- 如TS 2.6发行说明所述。描述严格的函数类型检查不包括方法
你说得对,这是不安全的。允许这种行为来简化从JS到TS的迁移是有道理的。好消息是,您可以通过使用
strictFunctionTypes
选择不允许这种行为
例如,此代码
declare const callbackImpl: (str: string) => number
let callback: (parameter: string | undefined) => number;
callback = callbackImpl
callback(undefined);
上面的代码使用strictNullChecks
编译,尽管它并不像您所注意到的那样是完全类型安全的。但它无法同时使用strictNullChecks
和strictFunctionTypes
注意我假设您已经在使用stricnullchecks
,如果您没有,那么代码将按预期工作,因为没有此选项string |未定义的
根据定义就是string
编辑
上面的一般解释是在问题包含实际代码之前发布的。编译器没有捕获错误的原因是您将回调定义为一个方法。如果将其定义为函数字段,编译器将捕获错误。我仍然不确定为什么会看到以下内容:
interface Props {
callback: (parameter: string | undefined) => number;
}
class A extends React.Component<Props> {
componentDidUpdate() {
this.props.callback(undefined);
}
}
class B extends React.Component {
private callbackImpl = (str: string): number => {
// Will crash if str is undefined
return str.length;
};
render() {
return (
<React.Fragment>
<A
// Error now
callback={this.callbackImpl}
/>
</React.Fragment>
);
}
}
界面道具{
回调:(参数:字符串|未定义)=>number;
}
类扩展了React.Component{
componentDidUpdate(){
this.props.callback(未定义);
}
}
类扩展了React.Component{
private callbackImpl=(str:string):number=>{
//如果str未定义,将崩溃
返回str.length;
};
render(){
返回(
更严格的检查适用于所有函数类型,但源自方法或construcor声明的函数类型除外。排除方法是为了确保泛型类和接口(如数组)继续以协变的方式进行关联。严格检查方法的影响将是一个更大的突破性变化,因为大量泛型类型将变得不变(即使如此,我们可能会继续探索这种更严格的模式)
我更新了我的答案,以反映添加的代码。感谢更新。如果你发现为什么它与函数字段而不是方法一起工作,我将非常高兴=)谢谢!这是一个相当谨慎的警告-不直观且危险。我个人等不及WebAssembly让我们摆脱荒谬的JavaScript遗产。
interface Props {
callback: (parameter: string | undefined) => number;
}
class A extends React.Component<Props> {
componentDidUpdate() {
this.props.callback(undefined);
}
}
class B extends React.Component {
private callbackImpl = (str: string): number => {
// Will crash if str is undefined
return str.length;
};
render() {
return (
<React.Fragment>
<A
// Error now
callback={this.callbackImpl}
/>
</React.Fragment>
);
}
}