import { knex, Knex } from '../types'; import { expectType } from 'tsd'; const clientConfig = { client: 'sqlite3', connection: { filename: './mydb.sqlite', }, }; const knexInstance = knex(clientConfig); const knex2 = knex({ ...clientConfig, log: { debug(msg: string) { // }, }, pool: { log: (msg: string, level: string) => { // }, }, }); knexInstance.initialize(); knexInstance.initialize({}); interface User { id: number; age: number; name: string; active: boolean; departmentId: number; } interface Department { id: number; departmentName: string; } interface Article { id: number; subject: string; body?: string; authorId?: string; } interface Ticket { name: string; from: string; to: string; at: Date; } // Interface to witness type compatibility interface ExtendsWitness { _t: T1; } // Ensure that Knex type with parameters is compatible with Knex with default parameters // // This ensures that a value of Parameterized Knex can always be passed to a function that // consumes unparameterized Knex. type _T1 = ExtendsWitness, Knex>; type _T2 = ExtendsWitness[]>, Knex>; type _T3 = ExtendsWitness[]>, Knex.Where>; type _T4 = ExtendsWitness, Knex.Where>; type _T5 = ExtendsWitness< Knex.QueryInterface>, Knex.QueryInterface >; type _T6 = ExtendsWitness, Knex.QueryBuilder>; type _T7 = ExtendsWitness< Knex.QueryBuilder, Knex.QueryBuilder >; type _T8 = ExtendsWitness, Knex.QueryBuilder>; type _T9 = ExtendsWitness, Knex.QueryBuilder>; type _T10 = ExtendsWitness, Knex.QueryBuilder>; // Ensure the return type of knex() is compatible with Knex with default parameters type _T2_1 = ExtendsWitness; declare module '../types/tables' { interface Tables { users_inferred: User; departments_inferred: Department; articles_inferred: Article; users_composite: Knex.CompositeTableType< User, { insert: 'insert' }, { update: 'update' } >; departments_composite: Knex.CompositeTableType< Department, { insert: 'insert' }, { update: 'update' } >; articles_composite: Knex.CompositeTableType< Article, { insert: 'insert' }, { update: 'update' } >; } } const main = async () => { expectType & { identifier: number }>>( await knexInstance .select(knexInstance.ref('id').as('identifier'), 'name') .from('users_inferred') ); expectType & { identifier: number }>>( await knexInstance .select(knexInstance.ref('id').as('identifier'), 'name') .from('users_composite') ); const r10 = await knexInstance .select( knexInstance.ref('id').as('identifier'), 'name', knexInstance.ref('age').as('yearsSinceBirth') ) .from('users'); type _TR10 = ExtendsWitness< (typeof r10)[0], { identifier: number; name: string; yearsSinceBirth: number } >; // FixMe // expectType>(r10); expectType< Array<{ identifier: number; name: string; yearsSinceBirth: number }> >( await knexInstance .select( knexInstance.ref('id').as('identifier'), 'name', knexInstance.ref('age').as('yearsSinceBirth') ) .from('users_inferred') ); expectType< Array<{ identifier: number; name: string; yearsSinceBirth: number }> >( await knexInstance .select( knexInstance.ref('id').as('identifier'), 'name', knexInstance.ref('age').as('yearsSinceBirth') ) .from('users_composite') ); expectType>( await knexInstance('users').select(knexInstance.ref('id'), { age: 'users.age', }) ); expectType>( await knexInstance('users_inferred').select(knexInstance.ref('id'), { age: 'users.age', }) ); expectType>( await knexInstance('users_composite').select(knexInstance.ref('id'), { age: 'users.age', }) ); expectType<{ id: number; age: any } | undefined>( await knexInstance('users') .select(knexInstance.ref('id'), { age: 'users.age' }) .first() ); expectType<{ id: number; age: any } | undefined>( await knexInstance('users_inferred') .select(knexInstance.ref('id'), { age: 'users.age' }) .first() ); expectType<{ id: number; age: any } | undefined>( await knexInstance('users_composite') .select(knexInstance.ref('id'), { age: 'users.age' }) .first() ); expectType>( (await knexInstance('users').select('id', 'name')).map((u) => ({ identifier: u.id, username: u.name, })) ); expectType>( (await knexInstance('users_inferred').select('id', 'name')).map((u) => ({ identifier: u.id, username: u.name, })) ); expectType>( (await knexInstance('users_composite').select('id', 'name')).map((u) => ({ identifier: u.id, username: u.name, })) ); expectType>( (await knexInstance.select('id', 'name').from('users')).map((u) => ({ identifier: u.id, username: u.name, })) ); expectType>( (await knexInstance.select('id', 'name').from('users_inferred')).map( (u) => ({ identifier: u.id, username: u.name, }) ) ); expectType>( (await knexInstance.select('id', 'name').from('users_composite')).map( (u) => ({ identifier: u.id, username: u.name, }) ) ); // This one is not strongly typed because `.from('users')` doesn’t reference a typed table // so the user type is `any`. expectType>( (await knexInstance.select('id', 'name').from('users')).map((u) => ({ identifier: u.id, username: u.name, })) ); expectType( (await knexInstance.select('id', 'name', 'age').from('users')).reduce( (maxAge: number, user) => (user.age > maxAge ? user.age : maxAge), 0 ) ); expectType( ( await knexInstance.select('id', 'name', 'age').from('users_inferred') ).reduce( (maxAge: number, user) => (user.age > maxAge ? user.age : maxAge), 0 ) ); expectType( ( await knexInstance.select('id', 'name', 'age').from('users_composite') ).reduce( (maxAge: number, user) => (user.age > maxAge ? user.age : maxAge), 0 ) ); expectType( ( await knexInstance('table') .select('key', 'value') .where({ namespace: 'foo' }) ).reduce( (aggr, { value, key }) => ({ ...aggr, [key]: value > 10 ? (aggr[key] || 0) + 1 : aggr[key], }), {} as any ) ); expectType>>( await knexInstance('users').select(['id', 'age']) ); expectType>>( await knexInstance('users_inferred').select(['id', 'age']) ); expectType>>( await knexInstance('users_composite').select(['id', 'age']) ); expectType | undefined>( await knexInstance('users').select(['id', 'age']).first() ); expectType | undefined>( await knexInstance('users_inferred').select(['id', 'age']).first() ); expectType | undefined>( await knexInstance('users_composite').select(['id', 'age']).first() ); // Not strongly typed since `'users'` is not referencing a typed table expectType(await knexInstance('users').select('users.id')); expectType>>( await knexInstance('users') .select(['id', 'age']) .clearSelect() .select(['name']) ); expectType>>( await knexInstance('users_inferred') .select(['id', 'age']) .clearSelect() .select(['name']) ); expectType>>( await knexInstance('users_composite') .select(['id', 'age']) .clearSelect() .select(['name']) ); expectType>>( await knexInstance('users') .select('id') .select('age') .clearSelect() .select('name') .select('departmentId') ); expectType>>( await knexInstance('users_inferred') .select('id') .select('age') .clearSelect() .select('name') .select('departmentId') ); expectType>>( await knexInstance('users_composite') .select('id') .select('age') .clearSelect() .select('name') .select('departmentId') ); expectType>>( await knexInstance .select('id') .select('age') .clearSelect() .select('name') .select('departmentId') .from('users') ); expectType>>( await knexInstance .select('id') .select('age') .clearSelect() .select('name') .select('departmentId') .from('users_inferred') ); expectType>>( await knexInstance .select('id') .select('age') .clearSelect() .select('name') .select('departmentId') .from('users_composite') ); // Not strongly typed since `'users'` is not referencing a typed table expectType( await knexInstance('users').select('users.id').select('age') ); // Not strongly typed since `'departments'` is not referencing a typed table expectType( await knexInstance('users').select('id').from('departments') ); // This one is typed because `'departments'` references a typed table expectType>>( await knexInstance('users') .select('id') .from('departments') ); expectType>>( await knexInstance('users_inferred') .select('id') .from('departments_inferred') ); expectType>>( await knexInstance('users_composite') .select('id') .from('departments_composite') ); // Not strongly typed since `'users'` is not referencing a typed table expectType(await knexInstance.select('id').from('users')); expectType>>( await knexInstance.select('id').from('users') ); expectType>>( await knexInstance.select('id').from('users_inferred') ); expectType>>( await knexInstance.select('id').from('users_composite') ); expectType>>( await knexInstance.select('id', 'age').from('users') ); expectType>>( await knexInstance.select('id', 'age').from('users_inferred') ); expectType>>( await knexInstance.select('id', 'age').from('users_composite') ); expectType>>( await knexInstance.from('users').select('id') ); expectType>>( await knexInstance.from('users_inferred').select('id') ); expectType>>( await knexInstance.from('users_composite').select('id') ); // Not strongly typed since `'users'` is not referencing a typed table expectType(await knexInstance.from('users').select('users.id')); // Force-casting the return to a narrower type (less common usage) expectType>>( await knexInstance .from('users') .select[]>('users.id') ); // Not strongly typed since `'users'` is not referencing a typed table expectType( await knexInstance.column('id', 'age').select().from('users') ); expectType>>( await knexInstance.column('id', 'age').select().from('users') ); expectType>>( await knexInstance.column('id', 'age').select().from('users_inferred') ); expectType>>( await knexInstance.column('id', 'age').select().from('users_composite') ); expectType>>( await knexInstance('users').column('id', 'age').select() ); expectType>>( await knexInstance('users_inferred').column('id', 'age').select() ); expectType>>( await knexInstance('users_composite').column('id', 'age').select() ); expectType>>( await knexInstance('users').column('id', 'age') ); expectType>>( await knexInstance('users_inferred').column('id', 'age') ); expectType>>( await knexInstance('users_composite').column('id', 'age') ); // Not strongly typed since `'users'` is not referencing a typed table expectType(await knexInstance('users').distinct('name', 'age')); expectType>>( await knexInstance('users').distinct('name', 'age') ); expectType>>( await knexInstance('users_inferred').distinct('name', 'age') ); expectType>>( await knexInstance('users_composite').distinct('name', 'age') ); expectType< Array> >(await knexInstance('users').distinct()); expectType< Array> >(await knexInstance('users_inferred').distinct()); expectType< Array> >(await knexInstance('users_composite').distinct()); expectType>(await knexInstance.select('*').from('users')); expectType>( await knexInstance.select('*').from('users_inferred') ); expectType>( await knexInstance.select('*').from('users_composite') ); }; class ExcelClient extends knex.Client {}