TypeScript检查对象索引值存在性时报错的解决与相关疑问
我定义了一个存储返回字符串的函数的对象:
const values: { [key: string]: () => string } = { a: () => 'a', b: () => 'b' };
随后编写了一个函数,通过传入的key参数查找该对象中的值,并在值存在时执行相应操作:
function foo(key: string) { const value = values[key]; if (value) { // Do something } }
此时TypeScript给出错误提示:This condition will always return true since this function is always defined. Did you mean to call it instead?
请问:
- 如何解决该错误?
- 为何未检查值是否存在就直接调用
value()时,TypeScript不会给出警告?
一、解决错误的方法
TypeScript报错的核心原因是你定义的values类型{ [key: string]: () => string }向TypeScript承诺了:任意字符串key对应的value都是一个返回string的函数,不存在undefined的可能。因此if (value)这个判断永远为真,属于多余的无效检查。
要修复这个问题,需要修正类型定义,让TypeScript意识到不存在的key会返回undefined:
方法1:显式允许值为undefined
修改类型,把值的类型设为(() => string) | undefined:
const values: { [key: string]: (() => string) | undefined } = { a: () => 'a', b: () => 'b' }; function foo(key: string) { const value = values[key]; if (value) { // Do something } }
方法2:使用Partial工具类型
Partial工具类型会将对象的所有属性转为可选,等价于上面的类型定义,写法更简洁:
const values: Partial<{ [key: string]: () => string }> = { a: () => 'a', b: () => 'b' }; function foo(key: string) { const value = values[key]; if (value) { // Do something } }
方法3:使用Record结合undefined
用Record类型可以更清晰地表达“字符串key对应函数或undefined”的关系:
const values: Record<string, (() => string) | undefined> = { a: () => 'a', b: () => 'b' };
二、直接调用value()无警告的原因
TypeScript的类型检查是基于你提供的类型注解来工作的。你定义values的类型为{ [key: string]: () => string },相当于明确告诉TypeScript:所有字符串key对应的value都是有效的函数。
基于这个类型承诺,TypeScript会默认values[key]一定是可调用的函数,因此直接调用value()时不会发出警告。但在实际运行时,如果传入了对象中不存在的key,value会是undefined,此时调用value()会抛出TypeError。
简单来说,TypeScript信任你编写的类型定义,不会主动去质疑类型与实际对象的不完全匹配——除非你通过类型定义明确告知它可能存在的边界情况。
内容的提问来源于stack exchange,提问作者user2248702

