- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
考虑以下三种类型,其中 MainType
是 Type1
和 Type2
的并集。如果 kind
为 "kind1"
,则 data
的类型应与 相同的
{msg: string}
类型2
interface Type1 {
kind: "kind1";
data: { msg: string };
}
interface Type2 {
kind: "kind2";
data: { msg2: string };
}
type MainType = Type1 | Type2;
这是第一种使用方法。
function func(obj: MainType) {
switch (obj.kind) {
case "kind1": return obj.data.msg;
case "kind2": return obj.data.msg2;
}
}
上面的代码没有给出错误并显示正确的自动完成。
但是当我们解构obj
时,它会给出错误。
function func({kind, data}: MainType) {
switch (kind) {
case "kind1": return data.msg;
case "kind2": return data.msg2;
}
}
错误是
Property
'msg'
does not exist on type'{ msg: string; } | { msg2: string; }'
也许这是非常基本的东西。但我对 ts 很陌生,所以我无法理解解构如何改变类型。请解释原因并告知有什么办法可以解决。
最佳答案
通过在函数参数级别使用解构,我们失去了 kind
和 data
之间的连接。因此,按kind
切换并不会缩小data
的范围,因为现在它们处于不同的数据结构中。
我可以说,您删除了 kind
和 data
之间的界限,这意味着您实际上引入了两个变量,其中一个变量的类型为 kind1 | kind2
和第二个类型为 { msg: string; } | { 消息2:字符串; }
。
结果我们不再有kind
形式的判别式。
下面是解构行为的等效代码:
const f = (t: MainType) => {
const kind = t.kind // "kind1" | "kind2";
const data = t.data // {msg: string;} | {msg2: string;}
}
是的,从逻辑 Angular 来看,您的代码完全没问题,它应该可以工作,因为我们知道这些字段之间的关系。不幸的是 TS 无法理解边界。
总结 - 不幸的是,除非您不将类型缩小到联合的特定成员,否则您不能使用解构,因为它会破坏字段之间的类型关系。
<小时/>我们可以考虑通过一些类型保护来解决方法。考虑以下示例:
const isKind1 = (kind: MainType['kind'], data: MainType['data']): data is Type1['data']
=> kind === 'kind1'
const isKind2 = (kind: MainType['kind'], data: MainType['data']): data is Type2['data']
=> kind === 'kind2'
const f = ({kind, data}: MainType) => {
if (isKind1(kind, data)) {
data // is { msg: string }
}
if (isKind2(kind, data)) {
data // is { msg2: string }
}
}
通过使用类型保护 isKind1
和 isKind2
,我们能够在这两个变量之间创建连接。但问题是我们不能再使用 switch
了,我们还有更多的代码,并且字段关系在函数中实现,而不是类型定义,这种方法很容易出错,因为我可以在函数中做与原始关系不同的关系类型正在定义。
需要明确的是,我表明这是可能的,但得不偿失,我建议保留原始实现而不进行解构。
关于javascript - 如何使受歧视的工会与解构一起工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59786104/
我一直在使用标记的联合类型来处理 typescript 歧视,但我遇到了一些奇怪的事情。如果我打开实际的对象属性,一切都会按预期工作。但是如果我使用解构,typescript 会报错。我认为它与编译时
我正在创建一个动态小部件,它可以是空的也可以是已填充的。它应该默认为空。当populated={true} , 我想要 totalGross和 totalNet需要的值。否则,不应允许使用这 2 个
我是一名优秀的程序员,十分优秀!