Skip to content

Commit eb588a0

Browse files
committed
fix(core): Improve typings
1 parent 0dfd817 commit eb588a0

3 files changed

Lines changed: 44 additions & 28 deletions

File tree

projects/ngqp/core/src/lib/model.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ export type OnChangeFunction<T> = (value: T) => void;
1616
/** TODO Documentation */
1717
export type ParamCombinator<T> = (previousValue: T, newValue: T) => Params;
1818

19+
/** TODO Documentation */
20+
export type Unpack<T> = T extends (infer U)[] ? U : T;
21+
1922
/** TODO Documentation */
2023
export interface QueryParamGroupValue {
2124
[ controlName: string ]: any;
@@ -28,17 +31,17 @@ export interface QueryParamControlOpts<T> {
2831
/** TODO Documentation */
2932
name: string;
3033
/** TODO Documentation */
31-
serialize: ParamSerializer<T>;
34+
serialize: ParamSerializer<Unpack<T>>;
3235
/** TODO Documentation */
33-
deserialize: ParamDeserializer<T>;
36+
deserialize: ParamDeserializer<Unpack<T>>;
3437
/** TODO Documentation */
35-
compareWith: Comparator<T>;
38+
compareWith: Comparator<Unpack<T>>;
3639
/** TODO Documentation */
3740
multi?: boolean;
3841
/** TODO Documentation */
3942
debounceTime?: number | null;
4043
/** TODO Documentation (+ not supported in multi-mode) */
41-
emptyOn?: T | null;
44+
emptyOn?: Unpack<T>;
4245
/** TODO Documentation (note: no controls / serializers, but finished values and non-recursive) */
4346
combineWith?: ParamCombinator<T>;
4447
}
@@ -153,13 +156,10 @@ export class QueryParamControl<T> {
153156
public readonly name: string | null;
154157

155158
/** TODO Documentation See QueryParamControlOpts */
156-
public readonly serialize: ParamSerializer<T>;
157-
158-
/** TODO Documentation See QueryParamControlOpts */
159-
public readonly deserialize: ParamDeserializer<T>;
159+
public readonly serialize: ParamSerializer<Unpack<T>>;
160160

161161
/** TODO Documentation See QueryParamControlOpts */
162-
public readonly compareWith: Comparator<T>;
162+
public readonly deserialize: ParamDeserializer<Unpack<T>>;
163163

164164
/** TODO Documentation See QueryParamControlOpts */
165165
public readonly multi: boolean;
@@ -210,7 +210,6 @@ export class QueryParamControl<T> {
210210
createEmptyOnDeserializer(deserialize, emptyOn),
211211
`Error while deserializing value for ${name}`
212212
);
213-
this.compareWith = compareWith;
214213
this.multi = multi;
215214
this.debounceTime = debounceTime;
216215
this.combineWith = combineWith;

projects/ngqp/core/src/lib/query-param-builder.service.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,18 @@ export class QueryParamBuilder {
4242
* Redirects to {@link stringParam}.
4343
* @see stringParam
4444
*/
45-
public param(opts: QueryParamControlOptsInput<string> & { multi: true }): QueryParamControl<string[]>;
45+
public param(opts: QueryParamControlOptsInput<string[]> & { multi: true }): QueryParamControl<string[]>;
4646
public param(opts: QueryParamControlOptsInput<string>): QueryParamControl<string>;
47-
public param(opts: QueryParamControlOptsInput<string>): QueryParamControl<string | string[]> {
47+
public param(opts: QueryParamControlOptsInput<string | string[]>): QueryParamControl<string | string[]> {
4848
return this.stringParam(opts);
4949
}
5050

5151
/**
5252
* TODO Documentation
5353
*/
54-
public stringParam(opts: QueryParamControlOptsInput<string> & { multi: true }): QueryParamControl<string[]>;
54+
public stringParam(opts: QueryParamControlOptsInput<string[]> & { multi: true }): QueryParamControl<string[]>;
5555
public stringParam(opts: QueryParamControlOptsInput<string>): QueryParamControl<string>;
56-
public stringParam(opts: QueryParamControlOptsInput<string>): QueryParamControl<string | string[]> {
56+
public stringParam(opts: QueryParamControlOptsInput<string | string[]>): QueryParamControl<string | string[]> {
5757
return new QueryParamControl({
5858
serialize: DEFAULT_STRING_SERIALIZER,
5959
deserialize: DEFAULT_STRING_DESERIALIZER,
@@ -65,9 +65,9 @@ export class QueryParamBuilder {
6565
/**
6666
* TODO Documentation
6767
*/
68-
public numericParam(opts: QueryParamControlOptsInput<number> & { multi: true }): QueryParamControl<number[]>;
68+
public numericParam(opts: QueryParamControlOptsInput<number[]> & { multi: true }): QueryParamControl<number[]>;
6969
public numericParam(opts: QueryParamControlOptsInput<number>): QueryParamControl<number>;
70-
public numericParam(opts: QueryParamControlOptsInput<number>): QueryParamControl<number | number[]> {
70+
public numericParam(opts: QueryParamControlOptsInput<number | number[]>): QueryParamControl<number | number[]> {
7171
return new QueryParamControl({
7272
serialize: DEFAULT_NUMBER_SERIALIZER,
7373
deserialize: DEFAULT_NUMBER_DESERIALIZER,
@@ -79,9 +79,9 @@ export class QueryParamBuilder {
7979
/**
8080
* TODO Documentation
8181
*/
82-
public booleanParam(opts: QueryParamControlOptsInput<boolean> & { multi: true }): QueryParamControl<boolean[]>;
82+
public booleanParam(opts: QueryParamControlOptsInput<boolean[]> & { multi: true }): QueryParamControl<boolean[]>;
8383
public booleanParam(opts: QueryParamControlOptsInput<boolean>): QueryParamControl<boolean>;
84-
public booleanParam(opts: QueryParamControlOptsInput<boolean>): QueryParamControl<boolean | boolean[]> {
84+
public booleanParam(opts: QueryParamControlOptsInput<boolean | boolean[]>): QueryParamControl<boolean | boolean[]> {
8585
return new QueryParamControl({
8686
serialize: DEFAULT_BOOLEAN_SERIALIZER,
8787
deserialize: DEFAULT_BOOLEAN_DESERIALIZER,
@@ -93,9 +93,9 @@ export class QueryParamBuilder {
9393
/**
9494
* TODO Documentation
9595
*/
96-
public customParam<T>(opts: QueryParamControlOpts<T> & { multi: true }): QueryParamControl<T[]>;
96+
public customParam<T>(opts: QueryParamControlOpts<T[]> & { multi: true }): QueryParamControl<T[]>;
9797
public customParam<T>(opts: QueryParamControlOpts<T>): QueryParamControl<T>;
98-
public customParam<T>(opts: QueryParamControlOpts<T>): QueryParamControl<T | T[]> {
98+
public customParam<T>(opts: QueryParamControlOpts<T | T[]>): QueryParamControl<T | T[]> {
9999
return new QueryParamControl(opts);
100100
}
101101

projects/ngqp/core/src/lib/query-param-group.directive.ts

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,19 @@ import { Subject } from 'rxjs';
44
import { concatMap, debounceTime, map, takeUntil, tap } from 'rxjs/operators';
55
import { NGQP_ROUTER_ADAPTER, NGQP_ROUTER_OPTIONS, RouterAdapter, RouterAdapterOptions } from './router-adapter/router-adapter.interface';
66
import { QueryParamNameDirective } from './query-param-name.directive';
7-
import { QueryParamControl, QueryParamGroup, QueryParamGroupValue } from './model';
7+
import { QueryParamControl, QueryParamGroup, QueryParamGroupValue, Unpack } from './model';
88
import { isMissing } from './util';
99

10+
/** TODO Documentation */
11+
function isMultiControl<T>(control: QueryParamControl<T | T[]>): control is QueryParamControl<T[]> {
12+
return control.multi;
13+
}
14+
15+
/** TODO Documentation */
16+
function hasArrayModel<T>(control: QueryParamControl<T | T[]>, model: T | T[]): model is T[] {
17+
return isMultiControl(control);
18+
}
19+
1020
/**
1121
* TODO Documentation
1222
*/
@@ -62,9 +72,7 @@ export class QueryParamGroupDirective implements OnInit, OnDestroy {
6272
this.routerAdapter.queryParamMap.subscribe(queryParamMap => {
6373
Object.keys(this.queryParamGroup.controls).forEach(controlName => {
6474
const control: QueryParamControl<any> = this.queryParamGroup.get(controlName);
65-
const newModel = control.multi
66-
? queryParamMap.getAll(control.name).map(control.deserialize)
67-
: control.deserialize(queryParamMap.get(control.name));
75+
const newModel = this.deserialize(control, queryParamMap.getAll(control.name));
6876

6977
// Get the directive, if it has been initialized yet.
7078
const directive = this.directives.find(dir => dir.name === controlName);
@@ -131,10 +139,8 @@ export class QueryParamGroupDirective implements OnInit, OnDestroy {
131139
this.queue$.next(params);
132140
}
133141

134-
private getParamsForModel(control: QueryParamControl<any>, model: any): Params {
135-
const newValue = control.multi
136-
? (model || <any[]>[]).map(control.serialize)
137-
: control.serialize(model);
142+
private getParamsForModel<T = any>(control: QueryParamControl<T | T[]>, model: T): Params {
143+
const newValue = this.serialize(control, model);
138144

139145
const combinedParams: Params = isMissing(control.combineWith)
140146
? {} : control.combineWith(control.value, model);
@@ -145,6 +151,17 @@ export class QueryParamGroupDirective implements OnInit, OnDestroy {
145151
};
146152
}
147153

154+
private serialize<T = any>(control: QueryParamControl<T | T[]>, model: T): string[] {
155+
return hasArrayModel(control, model)
156+
? (model || <T[]>[]).map(control.serialize)
157+
: [control.serialize(model)];
158+
}
159+
160+
private deserialize<T = any>(control: QueryParamControl<T>, values: string[]): Unpack<T> | Unpack<T>[] {
161+
const deserialized: Unpack<T>[] = values.map(control.deserialize);
162+
return isMultiControl(control) ? deserialized : deserialized[0];
163+
}
164+
148165
private get routerOptions(): RouterAdapterOptions {
149166
const groupOptions = this.queryParamGroup ? this.queryParamGroup.routerOptions : {};
150167

0 commit comments

Comments
 (0)