[英]TypeScript allows a function as React prop that conflicts with in-param of function signature?
为什么TypeScript类型检查器允许具有与定义不严格匹配的函数参数的prop?
具体来说,我定义了一个函数callbackImpl = (str: string): number
,并将其作为React prop参数定义为callback(parameter: string | undefined): number;
,令人惊讶的工作。
这对我来说不直观,在我看来非常危险!
但! 调用我认为正确的callbackImpl(undefined)
是行不通的。
一个完整的例子:
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.json
设置了"strict": true,
这是一个更完整的tsconfig.json
列表,省略了一些本地内容。
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"moduleResolution": "node",
"module": "esnext",
"allowSyntheticDefaultImports": true,
"target": "es6",
"jsx": "react",
"allowJs": true,
"strict": true,
"noEmitOnError": true,
"plugins": [],
"baseUrl": "./",
"paths": {
// Omitted
},
"lib": [
"es2017", // Object.entries support
"dom"
],
"types": ["gapi", "gapi.auth2", "node"]
},
"exclude": [
"node_modules"
]
}
难道我做错了什么? 我的tsconfig设置错了吗? 我误会了什么吗?
谢谢!
Titian Cernicova-Dragomir回答后的其他资源
你是对的,这是不安全的。 有一个理由允许此行为简化从JS到TS的迁移。 您可以通过使用strictFunctionTypes
选择不允许这样做的好消息。
例如这段代码
declare const callbackImpl: (str: string) => number
let callback: (parameter: string | undefined) => number;
callback = callbackImpl
callback(undefined);
上面的代码使用strictNullChecks
编译,即使它没有像你注意到的那样完全类型安全。 但它无法使用strictNullChecks
和strictFunctionTypes
进行编译
注意我假设你已经在使用strictNullChecks
如果你不是那么代码按预期工作,因为没有这个选项string|undefined
是定义只是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>
);
}
}
编辑
此行为是设计使然。 -strictFunctionTypes
标志不适用于原始PR中所述的方法
更严格的检查适用于所有函数类型,但源自method或construcor声明的函数类型除外。 特别排除方法以确保通用类和接口(例如Array)继续主要关联。 严格检查方法的影响将是一个更大的突破性变化,因为大量的泛型类型将变得不变(即便如此,我们可能会继续探索这种更严格的模式)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.