typescript - 如何使用 Array.prototype.find 为联合数组匹配正确的类型?
问题描述
我有以下类型:
type A = { style: 'A', x: string }
type B = { style: 'B', y: string }
type Union = A | B;
我试图A
在 a中找到 type 的元素Union[]
,如下所示:
const data: Union[] = [
{ style: 'A', x: 'test' },
{ style: 'B', y: 'test' },
]
const a: A | undefined = data.find(d => d.style === 'A');
但这会引发错误:
Type 'A | B | undefined' is not assignable to type 'A | undefined'.
Property 'x' is missing in type 'B' but required in type 'A'.
的谓词函数Array.prototype.find
找到正确的类型没有问题,我可以访问的属性A
没有任何问题:
是缺少细化的返回类型。
我能够解决它的唯一方法是使用 for 循环,但这感觉既麻烦又不必要。
let a: A | undefined;
for (let i = 0; i < data.length; i++) {
const val = data[i];
if (val.style === 'A') {
a = val;
break;
}
}
解决方案
您的谓词d => d.style === 'A'
被推断为 type (d: Union) => boolean
。
对于您想要的行为,它必须被推断为(d: Union) => d is A
,即用户定义的类型保护。这不会发生,因为 Typescript 从不推断函数是用户定义的类型保护;如果你想要它,你必须明确地将它声明为一个。如果你这样写,那么它可以工作:
function isA(d: Union): d is A {
return d.style === 'A';
}
const a: A | undefined = data.find(isA); // no error
实际上,当我开始写这个答案时,我会说这可能是不可能的,因为它需要Array.prototype.find
的返回类型取决于谓词是否是用户定义的类型保护。我不认为这是可能的,但显然它是; 我只是通过测试才发现它有效,所以我今天也学到了一些东西。
推荐阅读
- wordpress - 联系表格 7 在发送钩子之前设置变量
- javascript -
没有在 IE11 上显示任何数据,而对于 Chrome 来说,它的工作就像一个魅力 - google-apps-script - 如何计算 Google 表格列中具有值的单元格?
- matplotlib - Spyder v4.0.1 绘图和变量资源管理器的问题
- tendermint - 如何在招标安装中克服这个问题?
- authentication - 将参数从控制器传递到自定义 AuthorizationHandler
- javascript - 将 JavaScript 数组传递给 PHP 文件会返回空数组
- python - Python - 并行交互和比较字典中的列表和字典
- angular - Angular:是否可以在 Angular 模板中使用第三方库?
- azure - MS Access App 从任何地方连接到 Azure Sql Db