typescript - 有没有办法根据 Typescript 中函数的另一个参数来缩小参数的类型?
问题描述
我正在尝试为一些过滤器类型的操作创建一个迷你 DSL,并为它编写一些辅助方法。
说我有功能
const equals = (left, right) => {}
需要键入此函数,以使left
值是对象上的字段,并且right
是该对象类型的值。
如果我这样做const equals = <T> (left: keyof T, right: T[keyof T]) => {}
,我会接近但right
会缩小到可用的类型,T
而不仅仅是left
.
可以通过以下方式实现所需的行为:
const equals = <T, F extends keyof T>(left: F, right: T[F])
但这需要两个通用参数,这会破坏我围绕此函数的代码的类型推断链。理想情况下,我想根据第一个参数键入第二个参数。这可能吗?
谢谢
解决方案
您可能正在寻找以下几行的内容。解决方案是将一些类型验证逻辑移至智能构造函数。
// model
type PickPropertiesOfType<T, A> = Pick<
A,
{
[K in keyof A]: A[K] extends T ? K : never;
}[keyof A]
>;
export type Filter<A> =
| { kind: "Equals"; field: string & keyof A; value: A[string & keyof A] }
| { kind: "EqualsField"; field: string & keyof A; value: string & keyof A };
export const equalsOtherField = <A, K extends string & keyof PickPropertiesOfType<A[K], A>>(
field: string & K,
value: string & keyof PickPropertiesOfType<A[K], A>
): Filter<A> => ({
kind: "EqualsField",
field,
value: value,
});
export const equals = <A, K extends string & keyof A>(field: string & K, value: A[K]): Filter<A> => ({
kind: "Equals",
field,
value: value,
});
// example
type ExampleEntity = {
author: string;
publisher: string;
year: number;
}
const exampleEntity: ExampleEntity = {
author: "Foo",
publisher: "Foobar",
year: 2000
}
const filterArr: Filter<ExampleEntity>[] = [
equals("author", "Bar"),
equalsOtherField("author", "publisher"),
];
推荐阅读
- python-3.x - 用户输入未正确添加到 python 中的列表中
- node.js - 如何在 Mongoose/MongoDB 中聚合两个集合?
- c# - 创建将可变数量的成员映射到一个的映射器
- emacs - 名称中带有斜线的 Emacs 守护进程/服务器
- php - 结束日期大于php中的开始日期
- c# - 在 .NET Core 世界中中止线程的替代方法?
- python - 利用 asyncio 生成器和 asyncio.as_completed
- swift - 如何在我的 firebase 数据库中投射可能属于两种不同类型的引用
- azure - Azure Cosmos DB SQL API QueryDefinition 用于 WHERE IN 的多个参数
- swift - 在 swiftUI 视图模型中使用 FetchRequest