Я пытаюсь напечатать 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) ]
поскольку тип не сузился to 2 | 4 | 5
, TypeScript не выдает ошибку относительно аргумента 3
. Можем ли мы сделать что-нибудь с функцией is
, чтобы помочь ей правильно определить тип?