typescript - 解构歧视联合
问题描述
我正在尝试编写可与具有type
属性的通用可区分联合体一起使用的代码。
假设我有一堆受歧视的工会,例如:
interface IFoo {
type: "foo";
foo: number;
}
interface IBar {
type: "bar";
bar: number;
}
interface IBaz {
type: "baz";
baz: number;
}
type IObject = IFoo | IBar | IBaz;
我解决的第一个任务是确定类型属性的可能值:
declare let _object: IObject;
type ObjectType = typeof _object.type;
(顺便说一句,有没有办法在没有额外声明的情况下做同样的事情?)
我需要声明一个要使用的泛型类型,例如:
Case<IObject, "foo"> // = IFoo
Case<IObject, "bar"> // = IBar
这样我就可以声明:
function filter<Type extends ObjectType>(
objects: IObject[],
type: Type,
): Case<IObject, type>[] {
return objects.filter((o) => o.type == type);
}
这可能吗?
解决方案
是的,这是可能的
interface IFoo {
type: "foo";
foo: number;
}
interface IBar {
type: "bar";
bar: number;
}
interface IBaz {
type: "baz";
baz: number;
}
type IObject = IFoo | IBar | IBaz;
type TypeSwitch<N extends string, T extends { type: N }> =
{ [n in N]: T extends { type: n } ? T : never };
type Case<T extends { type: string }, N extends T['type']> =
TypeSwitch<T['type'], T>[N];
type F = Case<IObject, "foo">; // = IFoo
type B = Case<IObject, "bar">; // = IBar
此外,您可以使用“索引类型查询”类型运算符来引用属性的类型(实际上与使用属性访问的语法相同[]
,只是它对类型进行操作)
type ObjectType = IObject['type'];
最后,使用上述所有filter
内容可以按预期给出过滤后的数组元素的类型:
function filter<Type extends ObjectType>(
objects: IObject[],
type: Type,
): Case<IObject, Type>[] {
return objects.filter((o) => o.type == type);
}
let o: IObject[];
const a = filter(o, 'bar'); // inferred as const a: IBar[]
推荐阅读
- c# - Azure SpatialAnchors in Xamarin
- ios - 在密码文本输入期间是否有键盘大小更改的通知处理程序?
- vim - 以 JSON 格式列出给定文件夹的文件
- javascript - 我正在使用 react-native-elements 创建一个复选框列表。如何一次只检查一个框?
- java - 为什么responsebody注解返回String会导致ajax错误?
- r - 矩阵列表的for循环
- php - 如何将呼叫者连接到第三方,但在连接前向第三方宣布呼叫?
- python - 我如何在 python c++ 包装器中创建一个 const float*& 变量
- java - 尽管循环在数组长度范围内,但超出范围异常
- php - curl 的等效 php 选项