knex: Type definitions are broken in 0.21.10

Environment

Knex version: 0.21.10 Database + version: N/A OS: any TypeScript: 3.9.7, 4.0.5

@lorefnon

Bug

Type definitions are broken in 0.21.10.

Minimal test case:

npm init -y
npm i typescript knex @types/node

tsconfig.json (taken mostly from types/tsconfig.json):

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "ES2017",
    "lib": ["es6"],
    "noImplicitAny": true,
    "noImplicitThis": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "esModuleInterop": false
  }
}

index.ts:

import 'knex';

When running npx tsc: Actual result:

node_modules/knex/types/index.d.ts:338:26 - error TS2536: Type 'TTable' cannot be used to index type 'Tables'.

338 type TableType<TTable> = Tables[TTable];
                             ~~~~~~~~~~~~~~

node_modules/knex/types/index.d.ts:1243:33 - error TS2536: Type 'K' cannot be used to index type 'TRecord'.

1243       values: readonly DbColumn<TRecord[K]>[] | QueryCallback
                                     ~~~~~~~~~~

node_modules/knex/types/index.d.ts:1251:43 - error TS2536: Type 'K' cannot be used to index type 'TRecord'.

1251       values: readonly (readonly DbColumn<TRecord[K]>[])[] | QueryCallback
                                               ~~~~~~~~~~

node_modules/knex/types/index.d.ts:2144:1 - error TS2309: An export assignment cannot be used in a module with other exported elements.

2144 export = Knex;
     ~~~~~~~~~~~~~~


Found 4 errors.

Expected result: no errors

npm i knex@0.21.9 fixes the issue.

The bug was probably introduced in #4071

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 3
  • Comments: 21

Most upvoted comments

Sorry, wrong part of the documentation, correct one would be this:

Extending Query Builder

Important: this feature is experimental and its API may change in the future.

It allows to add custom function the the Query Builder.

Example:

const Knex = require('knex');
Knex.QueryBuilder.extend('customSelect', function(value) {
  return this.select(this.client.raw(`${value} as value`));
});

const meaningOfLife = await knex('accounts')
  .customSelect(42);

If using TypeScript, you can extend the QueryBuilder interface with your custom method.

    Create a knex.d.ts file inside a @types folder (or any other folder).

// knex.d.ts

import * as Knex from 'knex';

declare module 'knex' {
  interface QueryBuilder {
  customSelect<TRecord, TResult>(value: number): QueryBuilder<TRecord, TResult>;
}

    Add the new @types folder to typeRoots in your tsconfig.json.

// tsconfig.json

{
  "compilerOptions": {
    "typeRoots": [
      "node_modules/@types",
      "@types"
    ],
  }
}

I’ve got another question concerning the type enhancements, and I’m not sure whether this feature not documented, implemented, or has a bug:

I am unable to extend the QueryBuilder in a way that works with TypeScript. Is there an example for that in the documentation? I have a feeling that the Documentation sadly lacks a lot of examples for TypeScript use.

Sorry in advance if this is the wrong place for the question.

@PhilippMolitor This feature was reintroduced in 0.21.12, please give it a try!

Thanks for your quick and comprehensive reply. I wasn’t aware at all that this feature was brand new, I just started building my app on knex for the first time.

@PhilippMolitor Yes, we reverted that functionality since it was breaking TS builds. It will be back either today or early tomorrow in the next hotfix, depending on how fast CI cycle completes.