如何在柯里化函数中推断泛型?
Posted
技术标签:
【中文标题】如何在柯里化函数中推断泛型?【英文标题】:How to infer generic in a curried function? 【发布时间】:2020-08-20 19:22:37 【问题描述】:我正在尝试输入一个用于查询集合的 API。我希望它像这样使用:
interface Car
model: string
doors: 2 | 4 | 5
designers: string[]
const result = query(
model: [ contains('tesla') ],
doors: [ is(3) ],
designers: [ includes('Franz') ],
take: 5,
);
所以这是我不完美的方法:
type Query<Entity extends EntityType> = (config: QueryConfig<Entity>) => Promise<Entity[]>
type QueryConfig<Entity extends EntityType> =
[K in FilterScalarMembers<Entity>]?: ScalarBuilderFn<Entity[K]>[]
& [K in FilterCollectionMembers<Entity>]?: CollectionBuilderFn<Entity[K]>[]
& take: number ;
type FilterCollectionMembers<Entity extends EntityType> =
[K in keyof Entity]: Entity[K] extends CollectionType ? K : never [keyof Entity]
type FilterScalarMembers<Entity extends EntityType> =
[k in keyof Entity]: Entity[k] extends (string | number) ? k : never [keyof Entity]
type ScalarBuilderFn<T extends string | number> = (builder: ScalarQueryBuilder<T>) => ScalarQueryBuilder<T>
type CollectionBuilderFn<T extends CollectionType> = (builder: CollectionQueryBuilder<T>) => CollectionQueryBuilder<T>
type ScalarQueryBuilder<T extends string | number> =
type CollectionQueryBuilder<T extends CollectionType> =
type EntityType = Record<string, any>
type CollectionType = ((string | number)[]) | Set<string | number>
const is = <T extends string | number>(arg: T): ScalarBuilderFn<T> => function() as unknown as ScalarBuilderFn<T>;
问题在这里变得很明显:doors: [ is(3) ]
因为类型没有缩小到2 | 4 | 5
,TypeScript 不会给出关于3
参数的错误。我们可以对is
函数做些什么来帮助它正确推断类型吗?
【问题讨论】:
【参考方案1】:您可以使用indexed types:
const result = query(
doors: [is<Car['doors']>(3)]
);
您可以将is
传递给Car['doors']
的通用参数,这将告诉is
它的参数必须可分配给Car['doors']
,即2 | 4 | 5
。
我不确定您是否需要所有这些类型 - 除非它们执行此处未显示的其他操作。你所需要的只是is
有一个泛型类型参数,它的参数需要匹配
const is = <T>(val: T) => // rest of the implementation
【讨论】:
正如我所提到的,我希望从使用is
的上下文中推断出 is
参数类型。手动指定泛型类型很容易出错。以上是关于如何在柯里化函数中推断泛型?的主要内容,如果未能解决你的问题,请参考以下文章