Eri*_*vic 3 typescript reactjs
为什么 TypeScript 类型检查器允许 prop 的函数参数与定义不严格匹配?
具体来说,我定义了一个 function 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>
);
}
}
Run Code Online (Sandbox Code Playgroud)
我已经设置"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"
]
}
Run Code Online (Sandbox Code Playgroud)
难道我做错了什么?我的 tsconfig 设置错误吗?我误解了什么吗?
谢谢!
Titian Cernicova-Dragomir 回答后的其他资源
你是对的,这是不安全的。允许这种行为简化从 JS 到 TS 的迁移是有理由的。好消息是您可以通过使用strictFunctionTypes
.
例如这个代码
declare const callbackImpl: (str: string) => number
let callback: (parameter: string | undefined) => number;
callback = callbackImpl
callback(undefined);
Run Code Online (Sandbox Code Playgroud)
上面的代码编译通过,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>
);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑
此行为是设计使然。该-strictFunctionTypes
标志不适用于原始PR中所述的方法
更严格的检查适用于所有函数类型,除了那些源自方法或构造函数声明的函数类型。专门排除方法以确保通用类和接口(例如 Array)继续主要协变相关。严格检查方法的影响将是更大的破坏性变化,因为大量泛型类型将变得不变(即使如此,我们可能会继续探索这种更严格的模式)。
归档时间: |
|
查看次数: |
2950 次 |
最近记录: |