在 TypeScript 中感叹号 ( ! ) 运算符可以使编译器忽略一些错误,下面就来看看感叹号运算符有哪些实际的用途的以及何时使用。
1. 非空断言运算符
感叹号运算符称为非空断言运算符,添加此运算符会使编译器忽略undefined和null类型。来看例子:
const parseValue = (value: string) => {
// ...
};
const prepareValue = (value?: string) => {
// ...
parseValue(value);
};
对于 prepareValue 方法的 value 参数,TypeScript就会报出以下错误:
类型“string | undefined”的参数不能赋给类型“string”的参数。
不能将类型“undefined”分配给类型“string”。
类型“string | undefined”的参数不能赋给类型“string”的参数。不能将类型“undefined”分配给类型“string”。
因为我们希望 prepareValue 函数中的 value 是 undefined 或 string,但是我们将它传递给了 parseValue 函数,它的参数只能是 string。所以就报了这个错误。
但是,在某些情况下,我们可以确定 value 不会是 undefined,而这就是需要非空断言运算符的情况:
const parseValue = (value: string) => {
// ...
};
const prepareValue = (value?: string) => {
// ...
parseValue(value!);
};
这样就不会报错了。但是,在使用它时应该非常小心,因为如果 value 的值是undefined ,它可能会导致意外的错误。
2. 使用示例
既然知道了非空断言运算符,下面就来看几个真实的例子。
在列表中搜索是否存在某个项目:
interface Config {
id: number;
path: string;
}
const configs: Config[] = [
{
id: 1,
path: "path/to/config/1",
},
{
id: 2,
path: "path/to/config/2",
},
];
const getConfig = (id: number) => {
return configs.find((config) => config.id === id);
};
const config = getConfig(1);
由于搜索的内容不一定存在于列表中,所以 config 变量的类型是 Config | undefined,我们就可以使用可以使用费控断言运算符告诉 TypeScript,config 应该是存在的,因此不必假设它是 undefined。
const getConfig = (id: number) => {
return configs.find((config) => config.id === id)!;
};
const config = getConfig(1);
这时,config 变量的类型就是 Config。这时再从 config 中获取任何属性时,就不需要再检查它是否存在了。
再来看一个例子,React 中的 Refs 提供了一种访问 DOM 节点或 React 元素的方法:
const App = () => {
const ref = useRef<HTMLDivElement>(null);
const handleClick = () => {
if(ref.current) {
console.log(ref.current.getBoundingClientRect());
}
};
return (
<div className="App" ref={ref}>
<button onClick={handleClick}>Click</button>
</div>
);
};
这里创建了一个简单的组件,它可以访问 class 为 App 的 DOM 节点。组件中有一个按钮,当点击该按钮时,会显示元素的大小以及其在视口中的位置。我们可以确定被访问的元素是在点击按钮后挂载的,所以可以在 TypeScript 中添加非空断言运算符表示这个元素是一定存在的:
const App = () => {
const handleClick = () => {
console.log(ref.current!.getBoundingClientRect());
};
};
当使用非空断言运算符时,就表示告诉TypeScript,我比你更了解这个代码逻辑,会为此负责,所以我们需要充分了解自己的代码之后再确定是否要使用这个运算符。否则,如果由于某种原因断言不正确,则会发生运行时错误。