-
Notifications
You must be signed in to change notification settings - Fork 13
Description
Issue type:
[X] Question
[ ] Bug report
[X] Feature request
[X] Documentation issue
Database system/driver:
[X] Postgres
typed-knex version:
[X] 2.8.1
(or put your version here)
Knex.js version:
0.20.3
Steps to reproduce or a small repository showing the problem:
Hi Wouter,
I'm (once more) looking into the Typed Knex project. The current state looks quite nice and I like the new short and concise syntax.
During my first test I ran into a problem, which I think is not solvable with the current version, but might just need a better explanation in the docs.
What I'm trying to achieve is to get optional relations working properly. Suppose the following knex migration:
await knex.schema.createTable('groups', table => {
table.uuid('id').primary();
table.string('name');
});
await knex.schema.createTable('users', table => {
table.uuid('id').primary();
table.string('name');
table.uuid('groupId')
.nullable() // <-- Note the 'nullable()'
.references('id')
.inTable('groups');
});
const group1 = { id: uuidv4(), name: 'group 1' };
const user1 = { id: uuidv4(), name: 'user 1', groupId: group1.id };
const user2 = { id: uuidv4(), name: 'user 2', groupId: null }; // <-- this user does not have a group
await knex.insert(group1).into('groups');
await knex.insert(user1).into('users');
await knex.insert(user2).into('users');
The simplest Type Knex implementation of this model would be:
@Entity('groups')
export class Group {
@Column({ primary: true })
public id: string;
@Column()
public name: string;
}
@Entity('users')
export class User {
@Column({ primary: true })
public id: string;
@Column()
public name: string;
@Column({ name: 'groupId' })
public group: Group;
}
But then, performing queries on this:
const user1 = await typedKnex.query(User)
.where(i => i.name, 'user 1')
.leftOuterJoinColumn(i => i.group)
.select(i => [i.id, i.name, i.group.id, i.group.name])
.getFirst();
console.log(user1);
/*
{ id: '3c152f1a-c0d5-4343-984c-c829909db133',
name: 'user 1',
group:
{ id: '0663bcc3-fddb-4e18-976e-ae90e12fc3c9', name: 'group 1' } }
Ok, that's fine!
*/
const user2 = await typedKnex.query(User)
.where(i => i.name, 'user 2')
.leftOuterJoinColumn(i => i.group)
.select(i => [i.id, i.name, i.group.id, i.group.name])
.getFirst();
console.log(user2);
/*
{ id: 'c40bb9b6-12b1-4021-a7fb-44b19495e72c',
name: 'user 2',
group: { id: null, name: null } }
Hmm....
*/
The result of user2 is really awkward. The fact that user2.group is an object instead of null
is strange, and the typing of this object is incorrect because both fields in this object should be non-nullable.
Is there a way around this? The following does not work:
@Column({ name: 'groupId' })
public group: Group | null; // correct typing, but crashes the query builder
@Column({ name: 'groupId' })
public group?: Group; // somewhat correct typing, but crashes the query builder
Thanks!