Skip to content

Commit 399e09e

Browse files
Merge #1435
1435: Make `SearchResponse` types more strict regarding to pagination r=bidoubiwa a=fehnomenal # Pull Request ## Related issue Fixes #1434 ## What does this PR do? As described in #1434 with this PR the type of `SearchResponse` is determined by the params used for the search. ## PR checklist Please check if your PR fulfills the following requirements: - [x] Does this PR fix an existing issue, or have you listed the changes applied in the PR description (and why they are needed)? - [x] Have you read the contributing guidelines? - [x] Have you made sure that the title is accurate and descriptive of the changes? Thank you so much for contributing to Meilisearch! Co-authored-by: Andreas Fehn <[email protected]>
2 parents bcfd31e + 8b95468 commit 399e09e

File tree

3 files changed

+64
-15
lines changed

3 files changed

+64
-15
lines changed

src/indexes.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,14 @@ class Index<T extends Record<string, any> = Record<string, any>> {
7575
* @param config - Additional request configuration options
7676
* @returns Promise containing the search response
7777
*/
78-
async search<D extends Record<string, any> = T>(
78+
async search<
79+
D extends Record<string, any> = T,
80+
S extends SearchParams = SearchParams
81+
>(
7982
query?: string | null,
80-
options?: SearchParams,
83+
options?: S,
8184
config?: Partial<Request>
82-
): Promise<SearchResponse<D>> {
85+
): Promise<SearchResponse<D, S>> {
8386
const url = `indexes/${this.uid}/search`
8487

8588
return await this.httpRequest.post(
@@ -98,11 +101,14 @@ class Index<T extends Record<string, any> = Record<string, any>> {
98101
* @param config - Additional request configuration options
99102
* @returns Promise containing the search response
100103
*/
101-
async searchGet<D extends Record<string, any> = T>(
104+
async searchGet<
105+
D extends Record<string, any> = T,
106+
S extends SearchParams = SearchParams
107+
>(
102108
query?: string | null,
103-
options?: SearchParams,
109+
options?: S,
104110
config?: Partial<Request>
105-
): Promise<SearchResponse<D>> {
111+
): Promise<SearchResponse<D, S>> {
106112
const url = `indexes/${this.uid}/search`
107113

108114
const parseFilter = (filter?: Filter): string | undefined => {
@@ -125,7 +131,7 @@ class Index<T extends Record<string, any> = Record<string, any>> {
125131
attributesToHighlight: options?.attributesToHighlight?.join(','),
126132
}
127133

128-
return await this.httpRequest.get<SearchResponse<D>>(
134+
return await this.httpRequest.get<SearchResponse<D, S>>(
129135
url,
130136
removeUndefinedFromObject(getParams),
131137
config

src/types/types.ts

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,20 +123,51 @@ export type Hit<T = Record<string, any>> = T & {
123123

124124
export type Hits<T = Record<string, any>> = Array<Hit<T>>
125125

126-
export type SearchResponse<T = Record<string, any>> = {
126+
export type SearchResponse<
127+
T = Record<string, any>,
128+
S extends SearchParams | undefined = undefined
129+
> = {
127130
hits: Hits<T>
128131
processingTimeMs: number
129132
facetDistribution?: FacetDistribution
130133
query: string
131-
totalHits?: number
132-
hitsPerPage?: number
133-
page?: number
134-
totalPages?: number
135-
offset?: number
136-
limit?: number
137-
estimatedTotalHits?: number
134+
} & (undefined extends S
135+
? Partial<FinitePagination & InfinitePagination>
136+
: true extends IsFinitePagination<NonNullable<S>>
137+
? FinitePagination
138+
: InfinitePagination)
139+
140+
type FinitePagination = {
141+
totalHits: number
142+
hitsPerPage: number
143+
page: number
144+
totalPages: number
145+
}
146+
type InfinitePagination = {
147+
offset: number
148+
limit: number
149+
estimatedTotalHits: number
138150
}
139151

152+
type IsFinitePagination<S extends SearchParams> = Or<
153+
HasHitsPerPage<S>,
154+
HasPage<S>
155+
>
156+
157+
type Or<A extends boolean, B extends boolean> = true extends A
158+
? true
159+
: true extends B
160+
? true
161+
: false
162+
163+
type HasHitsPerPage<S extends SearchParams> = undefined extends S['hitsPerPage']
164+
? false
165+
: true
166+
167+
type HasPage<S extends SearchParams> = undefined extends S['page']
168+
? false
169+
: true
170+
140171
export type FieldDistribution = {
141172
[field: string]: number
142173
}

tests/search.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,8 +598,11 @@ describe.each([
598598

599599
expect(response.hits.length).toEqual(0)
600600

601+
// @ts-expect-error Property not existing on type
601602
expect(response.limit).toBeUndefined()
603+
// @ts-expect-error Property not existing on type
602604
expect(response.offset).toBeUndefined()
605+
// @ts-expect-error Property not existing on type
603606
expect(response.estimatedTotalHits).toBeUndefined()
604607

605608
expect(response.hitsPerPage).toEqual(0)
@@ -619,8 +622,11 @@ describe.each([
619622
})
620623

621624
expect(response.hits.length).toEqual(1)
625+
// @ts-expect-error Property not existing on type
622626
expect(response.limit).toBeUndefined()
627+
// @ts-expect-error Property not existing on type
623628
expect(response.offset).toBeUndefined()
629+
// @ts-expect-error Property not existing on type
624630
expect(response.estimatedTotalHits).toBeUndefined()
625631
expect(response.hitsPerPage).toEqual(1)
626632
expect(response.page).toEqual(1)
@@ -638,8 +644,11 @@ describe.each([
638644
})
639645

640646
expect(response.hits.length).toEqual(1)
647+
// @ts-expect-error Property not existing on type
641648
expect(response.limit).toBeUndefined()
649+
// @ts-expect-error Property not existing on type
642650
expect(response.offset).toBeUndefined()
651+
// @ts-expect-error Property not existing on type
643652
expect(response.estimatedTotalHits).toBeUndefined()
644653
expect(response.hitsPerPage).toEqual(1)
645654
expect(response.page).toEqual(1)
@@ -657,8 +666,11 @@ describe.each([
657666
})
658667

659668
expect(response.hits.length).toEqual(1)
669+
// @ts-expect-error Property not existing on type
660670
expect(response.limit).toBeUndefined()
671+
// @ts-expect-error Property not existing on type
661672
expect(response.offset).toBeUndefined()
673+
// @ts-expect-error Property not existing on type
662674
expect(response.estimatedTotalHits).toBeUndefined()
663675
expect(response.page).toEqual(1)
664676
expect(response.hitsPerPage).toEqual(1)

0 commit comments

Comments
 (0)