Skip to content

Commit

Permalink
feat(context): fix generic typing for BindingFilter
Browse files Browse the repository at this point in the history
  • Loading branch information
raymondfeng committed Apr 11, 2019
1 parent dcc9cac commit dafabbd
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 13 deletions.
26 changes: 20 additions & 6 deletions packages/context/src/binding-filter.ts
Expand Up @@ -10,16 +10,28 @@ import {BindingAddress} from './binding-key';
* A function that filters bindings. It returns `true` to select a given
* binding.
*/
export type BindingFilter<ValueType = unknown> = (
binding: Readonly<Binding<ValueType>>,
) => boolean;
export type BindingFilter = (binding: Readonly<Binding<unknown>>) => boolean;

export type BindingFilterGuard<T = unknown> = (
binding: Readonly<Binding<unknown>>,
) => binding is Readonly<Binding<T>>;

/**
* A helper function to cast a `BindingFilter` to a type guard
* @param filter A filter function
*/
export function asBindingFilterGuard<T = unknown>(
filter: BindingFilter,
): BindingFilterGuard<T> {
return filter as BindingFilterGuard<T>;
}

/**
* Select binding(s) by key or a filter function
*/
export type BindingSelector<ValueType = unknown> =
| BindingAddress<ValueType>
| BindingFilter<ValueType>;
| BindingFilter;

/**
* Type guard for binding address
Expand All @@ -35,7 +47,9 @@ export function isBindingAddress(
* Create a binding filter for the tag pattern
* @param tagPattern Binding tag name, regexp, or object
*/
export function filterByTag(tagPattern: BindingTag | RegExp): BindingFilter {
export function filterByTag<T = unknown>(
tagPattern: BindingTag | RegExp,
): BindingFilter {
if (typeof tagPattern === 'string' || tagPattern instanceof RegExp) {
const regexp =
typeof tagPattern === 'string'
Expand All @@ -58,7 +72,7 @@ export function filterByTag(tagPattern: BindingTag | RegExp): BindingFilter {
* Create a binding filter from key pattern
* @param keyPattern Binding key/wildcard, regexp, or a filter function
*/
export function filterByKey(
export function filterByKey<T = unknown>(
keyPattern?: string | RegExp | BindingFilter,
): BindingFilter {
if (typeof keyPattern === 'string') {
Expand Down
6 changes: 3 additions & 3 deletions packages/context/src/context-view.ts
Expand Up @@ -42,7 +42,7 @@ export class ContextView<T = unknown> extends EventEmitter

constructor(
protected readonly context: Context,
public readonly filter: BindingFilter<T>,
public readonly filter: BindingFilter,
) {
super();
}
Expand Down Expand Up @@ -161,10 +161,10 @@ export class ContextView<T = unknown> extends EventEmitter
*/
export function createViewGetter<T = unknown>(
ctx: Context,
bindingFilter: BindingFilter<T>,
bindingFilter: BindingFilter,
session?: ResolutionSession,
): Getter<T[]> {
const view = new ContextView(ctx, bindingFilter);
const view = new ContextView<T>(ctx, bindingFilter);
view.open();
return view.asGetter(session);
}
17 changes: 13 additions & 4 deletions packages/context/src/context.ts
Expand Up @@ -7,7 +7,12 @@ import * as debugFactory from 'debug';
import {EventEmitter} from 'events';
import {v1 as uuidv1} from 'uuid';
import {Binding, BindingTag} from './binding';
import {BindingFilter, filterByKey, filterByTag} from './binding-filter';
import {
asBindingFilterGuard,
BindingFilter,
filterByKey,
filterByTag,
} from './binding-filter';
import {BindingAddress, BindingKey} from './binding-key';
import {
ContextEventObserver,
Expand Down Expand Up @@ -38,7 +43,11 @@ if (!Symbol.asyncIterator) {
// tslint:disable-next-line:no-any
(Symbol as any).asyncIterator = Symbol.for('Symbol.asyncIterator');
}
// This import must happen after the polyfill
/**
* This following import must happen after the polyfill. The `auto-import` by
* an IDE such as VSCode may move the import before the polyfill. It must be
* fixed manually.
*/
import {iterator, multiple} from 'p-event';

const debug = debugFactory('loopback:context');
Expand Down Expand Up @@ -518,8 +527,8 @@ export class Context extends EventEmitter {
find<ValueType = BoundValue>(
pattern?: string | RegExp | BindingFilter,
): Readonly<Binding<ValueType>>[] {
const bindings: Readonly<Binding>[] = [];
const filter = filterByKey(pattern);
const bindings: Readonly<Binding<ValueType>>[] = [];
const filter = asBindingFilterGuard<ValueType>(filterByKey(pattern));

for (const b of this.registry.values()) {
if (filter(b)) bindings.push(b);
Expand Down

0 comments on commit dafabbd

Please sign in to comment.