在 React 中,经常会有这样的场景:通过某一个参数是否是真值,来决定某一个元素是否需要显示出来。
以 Ant Design 为例,Tooltip 的定义中,就包含了 title
这个参数,用于决定是否显示 Tooltip 及显示什么。如果传递的是 false
,null
或者 undefined
,那么最终 Tooltip 就不会被显示出来。
常用的调用形式可能如下:
<Tooltip title={!this.state.hide && 'text'} />
在最初 Ant Design 对此的定义上,使用了如下的 TypeScript 类型定义:
interface Props {
// ...
title?: React.ReactNode | RenderFunction;
// ...
}
这里,title
的定义用到了“可选参数”。看上去,是符合预期的行为,然而这里有几个细节值得注意:
React.ReactNode
的定义是:
type ReactNode =
ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
可以看到,即使不是可选参数,undefined
等一系列值也是可以赋予给 title
的;
title?: string
和title: string | undefined
之间存在着细微的差别。
这里展开对比一下 title?: string
和 title: string | undefined
之间的细微差别。如果定义的类型是 title?: string
,那么,以下的调用方式都是正确的:
- 传递字符串作为参数:
<Tooltip title="string" />
- 传递
undefined
作为参数:
<Tooltip title={undefined} />
- 不传递参数:
<Tooltip />
而如果是 title: string | undefined
,那么上面的第三种方案(即不传参数)就是不可行的。
还是以 Tooltip 为例,显然前两种调用方法都是真实存在的场景,毕竟 Tooltip 可能是需要根据外部条件来选择性展示的;但是对于第三种场景,即不提供 title
数据、一直保持不渲染 Tooltip 的状态,可以认为是有错误的,应该由 TypeScript 进行检查并报错。
故,改成以下这种形式就可以了,毕竟 React.ReactNode
就允许了 undefined
的使用:
interface Props {
// ...
title: React.ReactNode | RenderFunction;
// ...
}
Ant Design 对这种情况进行了修正。