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作为我的类型定义。
答案 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
,它不会再显示错误