为什么TypeScript类型检查器允许使用功能参数与定义不严格匹配的prop?
具体来说,我定义了一个函数callbackImpl = (str: string): number
,并将其作为定义为callback(parameter: string | undefined): number;
的React prop参数给出了。
这对我来说是不直观的,而且我认为这很危险!
但是!调用正确的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>
);
}
}
我在"strict": true,
中设置了tsconfig.json
这是一个更完整的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回答后的其他资源
答案 0 :(得分:4)
您是对的,这是不安全的。允许这种行为简化从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
更严格的检查适用于所有函数类型,但源于方法或构造函数声明的函数类型除外。专门排除了方法,以确保通用类和接口(例如Array)继续保持大多数协变关系。严格检查方法的影响将是一个重大突破,因为大量泛型类型将变为不变(即使如此,我们可能会继续探索这种更严格的模式)。