Skip to content

Commit

Permalink
Merge 983f23a into 501d58a
Browse files Browse the repository at this point in the history
  • Loading branch information
lorefnon committed Jun 7, 2019
2 parents 501d58a + 983f23a commit a5d4455
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 17 deletions.
45 changes: 28 additions & 17 deletions types/index.d.ts
Expand Up @@ -27,6 +27,7 @@ type StrKey<T> = string & keyof T;

// If T is unknown then convert to any, else retain original
type UnknownToAny<T> = ArrayIfAlready<T, unknown extends UnwrapArrayMember<T> ? any : UnwrapArrayMember<T>>;
type AnyToUnknown<T> = ArrayIfAlready<T, unknown extends UnwrapArrayMember<T> ? unknown : UnwrapArrayMember<T>>;

// Intersection conditionally applied only when TParams is non-empty
// This is primarily to keep the signatures more intuitive.
Expand Down Expand Up @@ -229,25 +230,35 @@ declare namespace DeferredKeySelection {
infer TIntersectProps,
infer TUnionProps
>
? AugmentParams<
TBase extends {}
? TSingle extends true
? TKeys extends keyof TBase
? TBase[TKeys]
: any
: AugmentParams<
true extends THasSelect ? PartialOrAny<TBase, TKeys> : TBase,
MappedAliasType<TBase, TAliasMapping>
>
: unknown,
TIntersectProps
> | TUnionProps
? UnknownToAny<
// ^ We convert final result to any if it is unknown for backward compatibility.
// Historically knex typings have been liberal with returning any and changing
// default return type to unknown would be a major breaking change for users.
//
// So we compromise on type safety here and return any.
AugmentParams<
AnyToUnknown<TBase> extends {}
// ^ Conversion of any -> unknown is needed here to prevent distribution
// of any over the conditional
? TSingle extends true
? TKeys extends keyof TBase
? TBase[TKeys]
: any
: AugmentParams<
true extends THasSelect ? PartialOrAny<TBase, TKeys> : TBase,
MappedAliasType<TBase, TAliasMapping>
>
: unknown,
TIntersectProps
> | TUnionProps
>
: TSelection;

// Resolution logic lifted over arrays of deferred selections
type Resolve<TSelection> = UnknownToAny<
ArrayIfAlready<TSelection, ResolveOne<UnwrapArrayMember<TSelection>>>
>;
type Resolve<TSelection> = TSelection extends DeferredKeySelection.Any
? ResolveOne<TSelection>
: TSelection extends DeferredKeySelection.Any[]
? ResolveOne<TSelection[0]>[]
: TSelection;
}

type AggregationQueryResult<TResult, TIntersectProps2> = ArrayIfAlready<
Expand Down
13 changes: 13 additions & 0 deletions types/test.ts
Expand Up @@ -74,12 +74,18 @@ const main = async () => {
// $ExpectType any[]
await knex('users');

// This test (others similar to it) may seem useless but they are needed
// to test for left-to-right inference issues eg: #3260
const u1: User[] = await knex('users');

// $ExpectType User[]
await knex<User>('users');

// $ExpectType any[]
await knex('users').select('id');

const u2: Partial<User>[] = await knex('users').select('id');

// $ExpectType any[]
await knex('users')
.select('id')
Expand All @@ -97,6 +103,8 @@ const main = async () => {
// $ExpectType any
await knex('users').first('id', 'name');

const u3: User = await knex('users').first('id', 'name');

// $ExpectType any
await knex('users').first(knex.ref('id').as('identifier'));

Expand Down Expand Up @@ -434,6 +442,11 @@ const main = async () => {

// ## Aggregation:

const u4: User[] = await knex('users')
.groupBy('count')
.orderBy('name', 'desc')
.having('age', '>', 10);

// $ExpectType User[]
await knex<User>('users')
.groupBy('count')
Expand Down

0 comments on commit a5d4455

Please sign in to comment.