type ExposedPromiseKeys = 'then' | 'finally' | 'catch'; type Promisish = Pick, keyof Promise & ExposedPromiseKeys>; abstract class Executable implements Promisish { private promise: Promise | null = null; protected abstract execute(): Promise; protected isExecuting(): boolean { return !!this.promise; } public then( onfulfilled?: | ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: | ((reason: unknown) => TResult2 | PromiseLike) | undefined | null ): Promise { if (!this.promise) { this.promise = this.execute(); } return this.promise.then(onfulfilled, onrejected); } public catch( onrejected?: | ((reason: unknown) => TResult | PromiseLike) | undefined | null ): Promise { return this.then(undefined, onrejected); } public finally(onfinally?: (() => void) | undefined | null): Promise { return this.then().finally(onfinally); } } type Keys = keyof T & string; type Filtered = T extends | null | undefined ? T : Omit, E>; type FilterExec = ( includes: Keys[] | undefined, excludes: Keys[] | undefined ) => Promise[]>; export class FilteredQuery< T, I extends keyof T = keyof T, E extends keyof T = never, > extends Executable[]> { private includes: Keys[] | undefined; private excludes: Keys[] | undefined; public constructor(private readonly exec: FilterExec) { super(); } protected execute(): Promise[]> { return this.exec(this.includes, this.excludes); } public include>( includes: NI[] | null ): FilteredQuery { this.includes = includes ?? undefined; return this as unknown as FilteredQuery; } public exclude>( excludes: NE[] | null ): FilteredQuery { this.excludes = excludes ?? undefined; return this as unknown as FilteredQuery; } }