繁体   English   中英

TypeScript允许函数作为React prop与函数签名的in-param冲突?

[英]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回答后的其他资源

  • 严格的函数类型 ,如TS 2.6发行说明中所述。 描述严格函数类型检查不涵盖方法。

你是对的,这是不安全的。 有一个理由允许此行为简化从JS到TS的迁移。 您可以通过使用strictFunctionTypes选择不允许这样做的好消息。

例如这段代码

declare const callbackImpl: (str: string) => number

let callback: (parameter: string | undefined) => number;

callback = callbackImpl

callback(undefined);

上面的代码使用strictNullChecks编译,即使它没有像你注意到的那样完全类型安全。 但它无法使用strictNullChecksstrictFunctionTypes进行编译

注意我假设你已经在使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM