【问题标题】:Typescript and React defaultProps are still being treated as possibly undefinedTypescript 和 React defaultProps 仍被视为可能未定义
【发布时间】: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 进行类型定义。

【问题讨论】:

    标签: reactjs typescript


    【解决方案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!()
    猜你喜欢
    • 2017-02-19
    • 2019-02-26
    • 2019-06-03
    • 2018-05-06
    • 2020-05-11
    • 2023-01-24
    • 2022-01-20
    • 1970-01-01
    • 2017-01-24
    相关资源
    最近更新 更多