Typescript和React defaultProps仍被视为未定义

时间:2017-08-24 17:19:59

标签: reactjs typescript

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了解无状态组件上的defaultProps

然而,Typescript仍会在常规组件定义中抱怨您的道具可能未定义(如上例所示)。

您可以使用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 个答案:

答案 0 :(得分:2)

因此,编译器说该对象可能是undefined。你知道的不是,所以你只想写this.props.foo()。正确的方法是使用null断言类型运算符

this.props.foo!()

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

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

另一方面,您可以创建extends PageProps的额外界面。为了好玩,我们称之为PagePropsFilled

interface PagePropsFilled extends PageProps {
    foo: Function;
}

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