Typescript 和 React defaultProps 仍被视为可能未定义

Posted

技术标签:

【中文标题】Typescript 和 React defaultProps 仍被视为可能未定义【英文标题】:Typescript and React defaultProps are still being treated as possibly undefined 【发布时间】:2018-02-02 16:30:05 【问题描述】:
interface PageProps 
    foo?: Function;
    bar: number;


export class PageComponent extends React.Component<PageProps, > 
    public static defaultProps: Partial<PageProps> = 
        foo: () => alert('Did foo')
    ;

    private doFoo() 
        this.props.foo(); // Typescript Error: Object is possibly 'undefined'
    

    public render(): JSX.Element 
        return (
            <div>
                <span>Hello, world! The number is this.props.bar</span>
                <button onClick=() => this.doFoo()>Do the Foo</button>
            </div>
        );
    

有没有办法告诉 Typescript props.foo总是被定义?

有一个很好的SO question and answer 讨论了如何正确定义组件上的道具类型。它甚至讨论了如何让 TS 知道 stateless 组件上的 defaultProps

但是,Typescript 仍然会在常规组件定义中抱怨您的 props 可能未定义(如我上面的示例所示)。

您可以使用 bang (this.props.foo!()) 调用它,这可以防止 TS 抛出错误,但它也可以防止对您传入的任何内容进行任何类型的检查。在上面的示例中,没什么大不了的.在更复杂的代码中,它已经咬了我。

所以我目前正在实施这样的事情:

private doFoo() 
    if (this.props.foo) this.props.foo();

这有一个缺点,我认为这很重要:它使我的代码有点混乱。实际上,我总是想调用this.props.foo(),但似乎,如果不更仔细地研究类,在doFoo 方法中什么都不会发生的情况。 (是的,我可以添加一条评论,解释 if 只是为了让 Typescript 高兴,但我宁愿我的代码在可能的时候自己说话。)

当我实际上需要从 this.props.foo() 返回某些内容时,我的代码变得更加复杂。

我目前正在使用 @types/react 进行类型定义。

【问题讨论】:

【参考方案1】:

所以,编译器说对象可能是undefined。你更清楚它不是,所以你只想写this.props.foo()。正确的做法是使用空断言类型运算符

this.props.foo!()

如果你说这之前已经咬过你,那是你自己没有检查它的错 :),这意味着编译器 - 正确 - 对象可能是 undefined。如果有可能是undefined,你应该经常检查它。也许您喜欢if 语句的更短版本?少了一个字符:

private doFoo() 
  this.props.foo && this.props.foo();

或使用打字稿 >= 3.8:

private doFoo() 
  this.props.foo?.();

另一方面,您可以创建一个额外的接口,即extends PageProps。为了好玩,我们就叫它PagePropsFilled

interface PagePropsFilled extends PageProps 
    foo: Function;

您现在可以将this.props 设置为PagePropsFilled,它不会再显示错误了

【讨论】:

今天你是我的英雄,让我免于为默认道具和道具做两个界面... hmmm 但是当我们需要输入interface 时,道具怎么可能是undefined?如果你通过undefined Typescript 应该抱怨它想要 Function,如果我们什么都不通过,它应该得到默认值。这令人困惑 @apieceofbart 如果接口属性写成foo?: Function,这意味着任何实现该接口的类都可以选择是否实现foo方法。如果它没有实现它,它将返回undefined。在接口中你不能有默认值 @PierreDuc 谢谢,我现在明白了。我的想法可能需要对 Typescript 进行一些更改才能使用 react defaultProps。我仍然认为这是一种耻辱,因为我们需要编写检查(if (this.props.foo).. 代码将永远为真 好吧,阅读我给出的答案。如果你确定它永远是真的,你可以使用null assertion type operator,像这样:this.props.foo!()

以上是关于Typescript 和 React defaultProps 仍被视为可能未定义的主要内容,如果未能解决你的问题,请参考以下文章

来自配置的 React 和 Typescript 动态组件

带有 React、TypeScript 和 Webpack 的空白页面

react-router 和 typescript 抛出“无法解析 'react-router-dom'”错误

深入浅出TypeScript- 在React项目中使用TypeScript

Esri 使用 React 和 Typescript 映射

React 和 TypeScript:避免使用上下文默认值