TypeScript中如何简洁处理字符串或含name属性的对象参数?
问题描述
我编写了一个可接收字符串或对象的简单函数:当参数为对象时使用其name属性,为字符串时直接使用该字符串。代码如下:
const foo = (bar: ({ name: string } | string)) => // 接收字符串或对象 bar?.name ?? bar; // 返回字符串或对象的name属性
但TypeScript抛出错误:
Property 'name' does not exist on type '(string | { name: string; })'.ts(2339)
实际运行时,传入字符串如foo('some string')时,'some string'?.name会返回undefined,最终结果正确,但TS不认可。我知道可以编写isString类型守卫函数来处理,但代码量较大,除了这种方式或使用@ts-ignore,还有更简洁的方案吗?
简洁解决方案
1. 类型断言结合可选链
通过类型断言告诉TypeScript,参数可能包含可选的name属性,同时保留原逻辑:
const foo = (bar: ({ name: string } | string)) => (bar as { name?: string })?.name ?? bar;
这种方式仅需添加一次类型断言,不会增加额外代码量,TS能正确识别类型逻辑。
2. 使用in操作符做类型窄化
利用TypeScript对in操作符的类型推导能力,直接通过条件判断完成类型窄化:
const foo = (bar: ({ name: string } | string)) => 'name' in bar ? bar.name : bar;
TS会自动判断:当'name' in bar为真时,bar是带name属性的对象;否则为字符串,逻辑清晰且无需额外函数。
3. 利用字符串内置name属性(不推荐)
JavaScript中字符串实例本身存在name属性(值为空字符串),因此可以直接去掉可选链:
const foo = (bar: ({ name: string } | string)) => bar.name ?? bar;
但该特性属于语言冷门细节,可读性差,依赖它会降低代码可维护性,不建议在生产环境使用。
内容的提问来源于stack exchange,提问作者machineghost
相关产品推荐
相关产品推荐

