- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
为什么 TypeScript 类型检查器允许带有不严格匹配定义的函数参数的 prop?
具体来说,我定义了一个函数callbackImpl = (str: string): number
,并将其作为定义为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
list ,省略了一些本地内容。
{
"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 中所述的方法
The stricter checking applies to all function types, except those originating in method or construcor declarations. Methods are excluded specifically to ensure generic classes and interfaces (such as Array) continue to mostly relate covariantly. The impact of strictly checking methods would be a much bigger breaking change as a large number of generic types would become invariant (even so, we may continue to explore this stricter mode).
关于reactjs - TypeScript 允许函数作为 React prop 与函数签名的 in-param 冲突吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52641612/
我的工作是将每条记录写入 Hadoop 映射中的 DynamoDB。 我无法使用具有 httpclient-4.2.5.jar 和 httpcore-4.2.5.jar 的 Hadoop 2.6 运行
我在 JavaScript 中嵌套了循环开关,例如: for (var i = 0; i < checkBoxIds.length; i++) { if ($('#' + checkB
我有一个文件夹被重命名的分支。现在我正在尝试合并从主干到这个分支的更改,但是在主干中修改的文件仍然在原始文件夹名称下,因此 svn 引发了树冲突。我该如何解决这个问题? 该文件夹已使用 svn ren
我在使用 jquery 暴露插件和 Masked 输入插件时遇到了问题。问题是它们都占用 $.mask 函数,从而导致冲突。但我非常需要这两个插件一起工作。我会将其中一个中的 $.mask 重命名为.
我正在尝试为我所有的 INPUT 元素做一个简单的 :focus 效果,就像这样: INPUT:focus { border-color: orange; } 这很好用,直到我将这段 CSS 添加到样
我是 javascript 的新手。 在 wordpress 上工作,我在自定义 js 中为我的主题输入了以下函数: document.getElementsByName("empty_cart")[
为什么有些 javascript 会与其他的发生冲突?我的意思是我一直在为图片库使用 javascript 代码,然后尝试在 jquery 中获取文本水印。为什么在使用 jquery 之后,画廊完全消
是否可以根据已知的输入值创建 MD5 碰撞? 所以例如我有输入字符串 abc与 MD5 900150983cd24fb0d6963f7d28e17f72 . 现在我想将字节添加到字符串 def获得相同
我在我的项目中使用原型(prototype): NodeParser.prototype.getChildren = function(parentContainer) { return fl
根据我对 merge 冲突的理解,当两个人更改了同一文件和/或修改了该文件中的同一行时,就会发生 merge 冲突。所以当我做一个 git pull origin master 我期望 merge 冲
iPad 上 Mobile Safari 中的 HTML5 模板。带 iScroll 的 Div 工作正常。 if/else 语句中还包含一个 jQuery 函数。该函数测试用户是否在 iScroll
我一直在尝试使 2 个脚本(1 个 mootol 和 1 个 jquery)在同一页面上工作,但没有成功。我一直在研究许多论坛等,但我仍然无法使这两个脚本同时工作。 这就是它在我的标题中的样子: /w
我想克隆带标题的问号。一切正常,但是当我将鼠标悬停在新问号上时,第一个问号上会出现工具提示。有什么想法吗? 我正在使用 jQuery 和醉酒的工具提示。 Demo here click here
好吧,我已经在一个 friend 的网站上工作了一段时间了。我的编码技能......值得怀疑,而且我遇到了很多问题。 目前我网站上的 jQuery 停止工作了,我找不到原因,并且我已尽一切努力让它工作
我想使用一个文件来保存所有#define 和常量:示例 #ifndef CONSTANTS_H_ #define CONSTANTS_H_ #include //OVERALL DEFS
我在我的表单中的所有 HTML 下都有一些验证码,这似乎阻止了我的复选框验证码的工作,一旦我在我的 HTML 下的代码周围添加/* */(使其不活动),我就得出了这个结论) 复选框验证代码开始正常工作
我是新手。我的页面上有两个 javascript/jquery。如果我使用第一个脚本,第二个脚本将不起作用。如果我删除第一个脚本,第二个脚本就可以正常工作。我不知道如何解决这个问题。我知道有一个“无冲
我是 Bison 新手,在处理 Shift/Reduce 冲突时遇到了麻烦... 我正在为C语言编写语法规则:ID是标识变量的标记,我编写此规则是为了确保即使将标识符写在括号中,也可以考虑它。 id
我目前正在使用 LibGdx 开发我的第一个 Android 游戏项目。这是一款 2D 迷宫游戏,您可以使用触摸输入从其中一个入口到其中一个导出“画出”一条线。世界本身是一个 TiledMap,目前仅
我正在尝试通过 javascript 完成表单验证,并在 #form# 标记中放置一个要执行的 .py 文件操作。但问题是,当我提交数据后,它不会重定向到 .py 操作。所以我摆脱了 preventd
我是一名优秀的程序员,十分优秀!