typescript - 根据数组文字区分联合
问题描述
我想使用数组中的文字从现有联合计算联合。
是否可以?
例子
interface Intf1 {
type: "one";
data: {
param: boolean;
};
}
interface Intf2 {
type: "two";
data: string;
}
interface Intf3 {
type: "three";
data: {
param: number;
};
}
const registered = ["one", "two"] as const;
type CombinedIntf = Intf1 | Intf2 | Intf3;
type CustomIntersect = ?
const getObj = () => {
return {} as any; // impl
};
const obj: CustomIntersect<CombinedIntf, typeof registered> = getObj();
// Intf1 | Intf2
switch(obj.type) {
case "one":
console.log(obj.data.param);
break;
case "two":
console.log(obj.param);
break;
case "three": // should give an error ""three" is not comparable to type "one", "two""
console.log(obj.param);
break;
}
谢谢!
解决方案
我认为你可以通过这种方式实现你想要的:
type CustomIntersect<T, R extends readonly PropertyKey[]> =
Extract<T, { type: R[number] }>
在这里,我使用了内置的Extract<T, U>
实用程序类型,它返回T
可分配给的联合的所有元素U
。由于您希望第二个类型参数R
是键数组的类型,因此我们将通过查找它的number
-keyed 属性来获得其元素类型的并集,如R[number]
. 通过Extract
ingT
可以分配给的所有工会成员{type: R[number]}
,我们应该只抓住那些你关心的成员:
const obj: CustomIntersect<CombinedIntf, typeof registered> = getObj();
// const obj: Intf1 | Intf2
switch (obj.type) {
case "one":
console.log(obj.data.param);
break;
case "two":
console.log(obj.data.toUpperCase()); // <-- changed this
break;
case "three": // error!
// ~~~~~~~
// Type '"three"' is not comparable to type '"one" | "two"'.(2678)
break;
}
推荐阅读
- javascript - 如何在我的计算器中存储结果并查看以前的计算?
- php - 如何使用 preg_replace PHP 从文件中删除文本
- python - 当我尝试将 numpy 数组作为第一个参数传递时,poly 函数是否只接受列表作为其第一个参数,它显示错误
- sql - 如何以编程方式为增量为两周的过去和未来添加开始日期和结束日期?
- list - Flutter 将搜索数据传递给 SearchDelegate
- java - 这是 Kotlin 中的数据构造“或”枚举类型吗?
- sql - sp_send_dbmail 的问题
- list - 了解守卫功能和列表理解
- python-3.x - 将内容类型文本/HTML 从 API 转换为 JSON
- unity3d - 如何在 Unity vr 中修复您的位置