Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Address concerns around count typings #3249

Merged
merged 4 commits into from Jun 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 13 additions & 10 deletions types/index.d.ts
Expand Up @@ -11,6 +11,7 @@
import events = require('events');
import stream = require('stream');
import Bluebird = require('bluebird');
import ResultTypes = require('./result');

// # Generic type-level utilities

Expand Down Expand Up @@ -86,7 +87,7 @@ type MappedAliasType<TBase, TAliasMapping> = {} & {
// but the keys being selected or additional properties being augmented are not
// all known at once and we would want to effectively build up a partial/intersection
// over multiple steps.
interface DeferredKeySelection<
type DeferredKeySelection<
// The base of selection. In intermediate stages this may be unknown.
// If it remains unknown at the point of resolution, the selection will fall back to any
TBase,
Expand All @@ -106,7 +107,7 @@ interface DeferredKeySelection<
TIntersectProps extends {} = {},
// Extra props which will be unioned with the result
TUnionProps = never
> {
> = {
// These properties are not actually used, but exist simply because
// typescript doesn't end up happy when type parameters are unused
_base: TBase;
Expand All @@ -116,7 +117,7 @@ interface DeferredKeySelection<
_single: TSingle;
_intersectProps: TIntersectProps;
_unionProps: TUnionProps;
}
};

// An companion namespace for DeferredKeySelection which provides type operators
// to build up participants of intersection/partial over multiple invocations
Expand Down Expand Up @@ -273,8 +274,7 @@ type AggregationQueryResult<TResult, TIntersectProps2> = ArrayIfAlready<
// deferring an index access operation (TBase[TKey]) over a potentially
// unknown initial type of TBase and potentially never initial type of TKey

interface DeferredIndex<TBase, TKey extends string>
extends DeferredKeySelection<TBase, TKey, false, {}, true> {}
type DeferredIndex<TBase, TKey extends string> = DeferredKeySelection<TBase, TKey, false, {}, true>;

declare namespace DeferredIndex {
type Augment<
Expand All @@ -297,9 +297,7 @@ type ResolveResult<S> = DeferredKeySelection.Resolve<S>;
type Callback = Function;
type Client = Function;

interface Dict<T = any> {
[k: string]: T;
}
type Dict<T = any> = { [k: string]: T; };

type SafePick<T, K extends keyof T> = T extends {} ? Pick<T, K> : any;

Expand Down Expand Up @@ -382,6 +380,11 @@ declare namespace Knex {

type TableDescriptor = string | Knex.Raw | Knex.QueryBuilder;

type Lookup<TRegistry extends {}, TKey extends string, TDefault = never> =
TKey extends keyof TRegistry ?
TRegistry[TKey] :
TDefault;

//
// QueryInterface
//
Expand Down Expand Up @@ -498,8 +501,8 @@ declare namespace Knex {
limit(limit: number): QueryBuilder<TRecord, TResult>;

// Aggregation
count: AssymetricAggregation<TRecord, TResult, number | string>;
countDistinct: AssymetricAggregation<TRecord, TResult, number | string>;
count: AssymetricAggregation<TRecord, TResult, Lookup<ResultTypes.Registry, "Count", number | string>>;
countDistinct: AssymetricAggregation<TRecord, TResult, Lookup<ResultTypes.Registry, "Count", number | string>>;
min: TypePreservingAggregation<TRecord, TResult>;
max: TypePreservingAggregation<TRecord, TResult>;
sum: TypePreservingAggregation<TRecord, TResult>;
Expand Down
27 changes: 27 additions & 0 deletions types/result.d.ts
@@ -0,0 +1,27 @@
// This empty interface serves as a placeholder which userland code can augment to
// override result types.
//
// Currently only available result type which is overridable is Count, which defaults to
// number | string;
//
// Following example in userland code will alter this to be just number:
//
// declare module "knex/types/result" {
// interface Registry {
// Count: number;
// }
// }
//
// Prior discussion: https://github.com/tgriesser/knex/issues/3247
export interface Registry {
// We can't actually have default types here
// because typescript's augmentation will not permit
// overriding the type of a property already present.
//
// But the effective defaults are documented below:
//
// Count: number | string;
//
// Refer to Knex.Lookup type operator to see how the defaults
// are actually specified.
}
3 changes: 2 additions & 1 deletion types/tslint.json
Expand Up @@ -9,6 +9,7 @@
"unified-signatures": false,
"no-unnecessary-qualifier": false,
"strict-export-declare-modifiers": false,
"only-arrow-functions": false
"only-arrow-functions": false,
"interface-over-type-literal": false
}
}