Typescript 如何在curried函数中推断泛型?

Typescript 如何在curried函数中推断泛型?,typescript,typescript-generics,Typescript,Typescript Generics,我正在尝试键入用于查询集合的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 Q

我正在尝试键入用于查询集合的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>;
type Query=(config:QueryConfig)=>Promise
类型查询配置=
{[K in FilterScalarMembers]?:ScalarBuilderFn[]}
&{[K in FilterCollectionMembers]?:CollectionBuilderFn[]}
&{take:number};
类型FilterCollectionMembers=
{[K-in-keyof-Entity]:Entity[K]扩展了CollectionType?K:never}[keyof-Entity]
类型过滤器CalArMembers=
{[k-in-keyof-Entity]:Entity[k]扩展(字符串|编号)?k:never}[keyof-Entity]
键入ScalarBuilderFn=(生成器:ScalarQueryBuilder)=>ScalarQueryBuilder
类型CollectionBuilderFn=(生成器:CollectionQueryBuilder)=>CollectionQueryBuilder
类型ScalarQueryBuilder={}
类型CollectionQueryBuilder={}
类型EntityType=记录
类型集合类型=((字符串|编号)[])|集
常量is=(arg:T):ScalarBuilderFn=>function(){}与ScalarBuilderFn一样未知;
问题在这里变得很明显:
doors:[is(3)]
由于类型没有缩小到
2 | 4 | 5
,TypeScript没有给出关于
3
参数的错误。我们可以对
is
函数做些什么来帮助它正确推断类型吗?

您可以使用:


正如我提到的,我希望从使用
is
的上下文中推断出
is
参数类型。手动指定泛型类型容易出错。
const result = query({
    doors: [is<Car['doors']>(3)]
});
const is = <T>(val: T) => { } // rest of the implementation