typescript - 打字稿中的联合类型推断
问题描述
type p1 = { a: number, b: string }
type p3 = { a: string }
type p4 = p1 | p3
let demo: p4 = { a: '123', b: '123' }
function isP3(obj: p4): obj is p3 {
return typeof (<p3>obj).a === 'string'
}
function func(obj: p4) {
if ('b' in obj) {
// Uncaught TypeError: obj.a.toFixed is not a function
obj.a.toFixed() //<- Now, no error is given
} else {
}
}
func(demo)
为什么demo初始化时没有报错?用户定义的类型保护
解决方案
这是 TypeScript 中的一个未解决问题 (microsoft/TypeScript#20863)。您的 union 类型不是可区分的 union ,因此编译器不会在执行多余的属性检查之前将 union 拆分为成员。大多数人(包括我自己)都希望工会的每个成员都应该进行过多的财产检查,无论工会是否是受歧视的工会。不过,目前情况就是这样:编译器认为这"b"
是至少一个联合成员的可接受属性,并决定不抱怨。
请注意,过多的属性检查是一种方便,而不是类型安全问题。TypeScript 中的对象类型是open,您始终可以在定义中添加更多属性而不违反类型。尽管具有该属性,但值{x: 1, y: 2}
是有效的。另一种说法是 TypeScript 中的对象类型并不精确。因此,从技术上讲,它是有效的,因此是有效的。因此,从技术上讲,您不能只检查是否存在来区分and 。是的,如果你只是试图说你会收到超额财产警告{x: number}
y
{ a: '123', b: '123' }
p3
p4
b
p1
p3
const demo: p3 = {a: '123', b: '123'}
"b"
,但正如我所说,这只是一种方便。它很容易被击败:
const demo1 = { a: '123', b: '123' };
const demo2: p3 = demo1; // no error
此时您可能会想:“等等,如果"b"
不能正确区分p1
,p3
为什么编译器会认为它在 内部func()
?”。好问题:
if ('b' in obj) { // why does the compiler think this narrows obj to p1?
obj.a.toFixed() // no error, but blows up at runtime
}
好吧,事实证明,类型in
保护是故意不健全的。从技术上讲,使用它并不安全,但人们会这样做,而且通常这不是问题。但这对你没有帮助。那好吧。
那么,你应该在这里做什么?如果您的意图是进行b
区分p1
and的测试p3
,那么您的p3
类型应该明确说明:
type p3 = { a: string, b?: undefined }; // p3 cannot have a defined "b" property
现在,从 TypeScript 3.2+ 开始p4
,该类型是一个真正的可区分联合。所以这是一个错误:
let demo: p4 = { a: '123', b: '123' } // error now
并使不健全的'b'
测试显示为错误。如果你想做一个“好”的b
测试,你现在可以测试obj.b !== undefined
,这肯定会区分 ap1
和p3
新p3
定义:
function func(obj: p4) {
if ('b' in obj) {
obj.a.toFixed() // error now
}
if (obj.b !== undefined) {
obj.a.toFixed(); // okay
}
}
好的,希望有帮助;祝你好运!
推荐阅读
- loops - 如何在 SPSS 上创建以下变量?
- python - 使用键盘库如何在 .is_pressed 中使用组合键?
- javascript - 状态更新未反映在自定义挂钩中
- ethereum - 将 nonReentrant 修饰符与应付函数一起使用会导致错误吗?
- javascript - 使用 Axios 使用 HTTP Put 上传文件,而不包含在请求正文中
- scrapy - Scrapy css 选择器找不到结果 - 但浏览器可以
- sql - 如何在单独的框中查询国家/地区列表?
- td-engine - 在 tdengine 中创建表失败
- javascript - 如何导入具有 nodejs 16 类型的模块?
- reactjs - MUI 导航选项卡不适用于 react-router