diff --git a/types/index.d.ts b/types/index.d.ts index c66e35f9..d0aa1bd6 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -11,6 +11,7 @@ import events = require('events'); import stream = require('stream'); import Bluebird = require('bluebird'); +import ResultTypes = require('./result'); // # Generic type-level utilities @@ -86,7 +87,7 @@ type MappedAliasType = {} & { // 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, @@ -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; @@ -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 @@ -273,8 +274,7 @@ type AggregationQueryResult = 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 - extends DeferredKeySelection {} +type DeferredIndex = DeferredKeySelection; declare namespace DeferredIndex { type Augment< @@ -297,9 +297,7 @@ type ResolveResult = DeferredKeySelection.Resolve; type Callback = Function; type Client = Function; -interface Dict { - [k: string]: T; -} +type Dict = { [k: string]: T; }; type SafePick = T extends {} ? Pick : any; @@ -382,6 +380,11 @@ declare namespace Knex { type TableDescriptor = string | Knex.Raw | Knex.QueryBuilder; + type Lookup = + TKey extends keyof TRegistry ? + TRegistry[TKey] : + TDefault; + // // QueryInterface // @@ -498,8 +501,8 @@ declare namespace Knex { limit(limit: number): QueryBuilder; // Aggregation - count: AssymetricAggregation; - countDistinct: AssymetricAggregation; + count: AssymetricAggregation>; + countDistinct: AssymetricAggregation>; min: TypePreservingAggregation; max: TypePreservingAggregation; sum: TypePreservingAggregation; diff --git a/types/result.d.ts b/types/result.d.ts new file mode 100644 index 00000000..98fcbdbf --- /dev/null +++ b/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. +} diff --git a/types/tslint.json b/types/tslint.json index bc3b52e7..69846155 100644 --- a/types/tslint.json +++ b/types/tslint.json @@ -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 } }