diff --git a/packages/search-types/src/facet/filter/boolean-filter.model.ts b/packages/search-types/src/facet/filter/boolean-filter.model.ts index 9555f816b5..607bfcd2fe 100644 --- a/packages/search-types/src/facet/filter/boolean-filter.model.ts +++ b/packages/search-types/src/facet/filter/boolean-filter.model.ts @@ -1,8 +1,9 @@ -import { BooleanFilterModelName } from '../../named-model.model'; +import { BooleanFilterModelName, BooleanFilterModelNames } from '../../named-model.model'; +import { FacetFilter } from './facet-filter.model'; import { Filter } from './filter.model'; /** - * A boolean filter used in a {@link Facet}, which status can be selected or not and + * A boolean filter used in a {@link FacetFilter}, which status can be selected or not and * it may contains the total results number that the filter should return. * * @remarks It is like an "abstract" interface because it is not going to be implemented @@ -10,15 +11,13 @@ import { Filter } from './filter.model'; * * @public */ -export interface BooleanFilter extends Filter { - /** Type to narrow {@link ModelNameType} from the extended Filter for the known subtypes. */ - modelName: BooleanFilterModelName; - /** Text to render the filter label. */ - label: string; - /** Value to be sent to the backend. */ - value: string; - /** Amount of matching results. **/ - totalResults?: number; +export interface BooleanFilter extends FacetFilter { + /** Text to render the filter label. */ + label: string; + /** Type to narrow {@link ModelNameType} from the extended Filter for the known subtypes. */ + modelName: BooleanFilterModelName; + /** Amount of matching results. **/ + totalResults?: number; } /** @@ -29,5 +28,5 @@ export interface BooleanFilter extends Filter { * @public */ export function isBooleanFilter(filter: Filter): filter is BooleanFilter { - return 'label' in filter && 'value' in filter; + return BooleanFilterModelNames.includes(filter.modelName as BooleanFilterModelName); } diff --git a/packages/search-types/src/facet/filter/editable-number-range-filter.model.ts b/packages/search-types/src/facet/filter/editable-number-range-filter.model.ts index 6731533d89..c4e3e2ef7a 100644 --- a/packages/search-types/src/facet/filter/editable-number-range-filter.model.ts +++ b/packages/search-types/src/facet/filter/editable-number-range-filter.model.ts @@ -1,19 +1,20 @@ +import { FacetFilter } from './facet-filter.model'; import { Filter } from './filter.model'; import { RangeValue } from './range-value.model'; /** - * A type of filter used in {@link EditableNumberRangeFacet} and extends from {@link Filter}. + * A type of filter used in {@link EditableNumberRangeFacet} and extends from {@link FacetFilter}. * This filter has the particularity that its {@link RangeValue} is editable by the user. Editable means * that the value max and min can be changed by the user instead of having several boolean filters with different * values. * * @public */ -export interface EditableNumberRangeFilter extends Filter { - /** Model name to indicate the filter type. */ - modelName: 'EditableNumberRangeFilter'; - /** Filter range to use in the frontend. */ - range: RangeValue; +export interface EditableNumberRangeFilter extends FacetFilter { + /** Model name to indicate the filter type. */ + modelName: 'EditableNumberRangeFilter'; + /** Filter range to use in the frontend. */ + range: RangeValue; } /** @@ -23,6 +24,8 @@ export interface EditableNumberRangeFilter extends Filter { * * @public */ -export function isEditableNumberRangeFilter(filter: Filter): filter is EditableNumberRangeFilter { - return filter.modelName === 'EditableNumberRangeFilter'; +export function isEditableNumberRangeFilter( + filter: Filter +): filter is EditableNumberRangeFilter { + return filter.modelName === 'EditableNumberRangeFilter'; } diff --git a/packages/search-types/src/facet/filter/raw-filter.model.ts b/packages/search-types/src/facet/filter/raw-filter.model.ts index fd7a396fc0..6bd210a605 100644 --- a/packages/search-types/src/facet/filter/raw-filter.model.ts +++ b/packages/search-types/src/facet/filter/raw-filter.model.ts @@ -6,12 +6,12 @@ import { Filter } from './filter.model'; * @public */ export interface RawFilter extends Filter { - /** Model name to indicate the filter type. */ - modelName: 'RawFilter'; - /** The value of the filter. */ - id: string; - /** Force {@link Filter#selected | Filter selected} property to true */ - selected: true; + /** The value of the filter. */ + id: string; + /** Model name to indicate the filter type. */ + modelName: 'RawFilter'; + /** Force {@link Filter#selected | Filter selected} property to true */ + selected: true; } /** @@ -22,5 +22,5 @@ export interface RawFilter extends Filter { * @public */ export function isRawFilter(filter: Filter): filter is RawFilter { - return filter.modelName === 'RawFilter'; + return filter.modelName === 'RawFilter'; } diff --git a/packages/search-types/src/named-model.model.ts b/packages/search-types/src/named-model.model.ts index 80b8300b27..638511c1ca 100644 --- a/packages/search-types/src/named-model.model.ts +++ b/packages/search-types/src/named-model.model.ts @@ -4,18 +4,18 @@ * @public */ export type ModelNameType = - 'Result' - | 'NextQueries' - | 'NextQuery' - | 'RelatedTag' - | 'PopularSearch' - | 'QuerySuggestion' - | 'HistoryQuery' - | 'Banner' - | 'Promoted' - | FilterModelName - | FacetModelName - | string; + | 'Result' + | 'NextQueries' + | 'NextQuery' + | 'RelatedTag' + | 'PopularSearch' + | 'QuerySuggestion' + | 'HistoryQuery' + | 'Banner' + | 'Promoted' + | FilterModelName + | FacetModelName + | string; /** * Common interface to ease the differentiate between different model types. @@ -32,7 +32,11 @@ export interface NamedModel { * * @public */ -export type FacetModelName = 'SimpleFacet' | 'HierarchicalFacet' | 'NumberRangeFacet' | 'EditableNumberRangeFacet'; +export type FacetModelName = + | 'SimpleFacet' + | 'HierarchicalFacet' + | 'NumberRangeFacet' + | 'EditableNumberRangeFacet'; /** * Filters model names type. It can be: {@link BooleanFilterModelName}, RawFilter or EditableNumberRangeFilter. @@ -41,9 +45,18 @@ export type FacetModelName = 'SimpleFacet' | 'HierarchicalFacet' | 'NumberRangeF */ export type FilterModelName = BooleanFilterModelName | 'EditableNumberRangeFilter' | 'RawFilter'; +/** + * Const to use in the {@link BooleanFilterModelName} Type definition and also in Type Guards. + */ +export const BooleanFilterModelNames = [ + 'SimpleFilter', + 'HierarchicalFilter', + 'NumberRangeFilter' +] as const; + /** * Type to ease the usage of a model name in a {@link BooleanFilter} with autocomplete suggestions. * * @public */ -export type BooleanFilterModelName = 'SimpleFilter' | 'HierarchicalFilter' | 'NumberRangeFilter' | string; +export type BooleanFilterModelName = typeof BooleanFilterModelNames[number]; diff --git a/packages/search-types/src/schemas/filter.schema.ts b/packages/search-types/src/schemas/filter.schema.ts index d56620b470..40e5e7afe7 100644 --- a/packages/search-types/src/schemas/filter.schema.ts +++ b/packages/search-types/src/schemas/filter.schema.ts @@ -15,7 +15,7 @@ import { IdentifiableSchema } from './identifiable.schema'; export const FilterSchema: Filter = { ...IdentifiableSchema, modelName: expect.any(String), - selected: expect.any(Boolean), + selected: expect.any(Boolean) }; /** @@ -26,7 +26,7 @@ export const FilterSchema: Filter = { export const FacetFilterSchema: FacetFilter = { ...FilterSchema, facetId: expect.anyOf([Number, String]), - modelName: expect.any(String) && expect.not.stringMatching('RawFilter') + modelName: expect.any(String) }; /** @@ -48,8 +48,8 @@ export const RawFilterSchema: RawFilter = { */ export const BooleanFilterSchema: BooleanFilter = { ...FacetFilterSchema, + modelName: expect.any(String), label: expect.any(String), - value: expect.any(String), totalResults: expect.undefinedOr(Number) }; @@ -60,7 +60,7 @@ export const BooleanFilterSchema: BooleanFilter = { */ export const SimpleFilterSchema: SimpleFilter = { ...BooleanFilterSchema, - modelName: 'SimpleFilter', + modelName: 'SimpleFilter' }; /** @@ -92,7 +92,7 @@ export const NumberRangeFilterSchema: NumberRangeFilter = { * @public */ export const EditableNumberRangeFilterSchema: EditableNumberRangeFilter = { - ...FilterSchema, + ...FacetFilterSchema, range: { min: expect.nullOr(Number), max: expect.nullOr(Number) }, modelName: 'EditableNumberRangeFilter' };