为什么类型推断在示例 A 中有效,而在 B 中无效?唯一的区别是类型字符串的位置。block.type与block.meta.type. A 编译并推断类型和 B 结果。
// Example B errors
Property 'a' does not exist on type 'Block'. Property 'a' does not exist on type 'ITwo'.
Property 'b' does not exist on type 'Block'. Property 'b' does not exist on type 'IOne'.
Run Code Online (Sandbox Code Playgroud)
如何在不更改IOneor的数据结构的情况下让 B 进行编译和正确推断ITwo?
示例 A
// Example B errors
Property 'a' does not exist on type 'Block'. Property 'a' does not exist on type 'ITwo'.
Property 'b' does not exist on type 'Block'. Property 'b' does not exist on type 'IOne'.
Run Code Online (Sandbox Code Playgroud)
示例 B
enum TYPE { ONE = 'one', TWO = 'two'}
interface IOne {
a: string,
type: TYPE.ONE
}
interface ITwo {
b: string,
type: TYPE.TWO
}
type Block = IOne | ITwo
[].map((block:Block) => {
switch (block.type) {
case TYPE.ONE:
block.a
break;
case TYPE.TWO:
block.b
break;
}
});
Run Code Online (Sandbox Code Playgroud)
提前致谢,J。
这在 TS 存储库中的嵌套标记联合问题下进行了讨论和跟踪。对您的问题的简短回答:在问题得到解决之前,您将无法执行您想要的操作。
也就是说,您仍然可以通过类型保护和泛型的组合来实现这一点。类型保护将执行运行时检查,确保嵌套值与预期类型匹配,并且泛型将删除一些样板文件,否则需要检查联合中的每种类型。
由于我们正在讨论的示例非常抽象,因此这可能不是您现实世界代码的实用解决方案。
假设只有少数类型,那么删除 switch 语句以支持条件返回(“尽早返回,经常返回”)是有意义的。这将使使用类型保护变得微不足道:
enum TYPE { ONE = 'one', TWO = 'two'}
interface IOne {
a: string,
meta : {
type: TYPE.ONE
}
}
interface ITwo {
b: string,
meta : {
type: TYPE.TWO
}
}
type Block = IOne | ITwo;
export const isBlock = <T extends Block>(
b: Block,
metaType: TYPE,
): b is T =>
b.meta.type === metaType;
[].map((block: Block) => {
if (isBlock<IOne>(block, TYPE.ONE)) {
return block.a;
}
return block.b;
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
171 次 |
| 最近记录: |