K
Kysely•2y ago
Dr. Sauce

Type of query result is {}[]

Hi all! Loving using Kysely at the moment, it's super easy to use. I ran into one problem, which I believe is probably a lack of understanding from myself around certain elements of TypeScript or Kysely itself. Here is the DB Schema from kysely-codegen:
import type { ColumnType } from "kysely";

export type Generated<T> = T extends ColumnType<infer S, infer I, infer U>
? ColumnType<S, I | undefined, U>
: ColumnType<T, T | undefined, T>;

export type Numeric = ColumnType<string, string | number, string | number>;

export type Timestamp = ColumnType<Date, Date | string, Date | string>;

export interface Disease {
id: Generated<string>;
coding_id: string;
coding_id_string: string;
description: string;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
}

export interface DiseaseTermSimilarity {
id: Generated<string>;
source_disease_id: string;
target_disease_id: string;
distance: Numeric;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
}
import type { ColumnType } from "kysely";

export type Generated<T> = T extends ColumnType<infer S, infer I, infer U>
? ColumnType<S, I | undefined, U>
: ColumnType<T, T | undefined, T>;

export type Numeric = ColumnType<string, string | number, string | number>;

export type Timestamp = ColumnType<Date, Date | string, Date | string>;

export interface Disease {
id: Generated<string>;
coding_id: string;
coding_id_string: string;
description: string;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
}

export interface DiseaseTermSimilarity {
id: Generated<string>;
source_disease_id: string;
target_disease_id: string;
distance: Numeric;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
}
Here is a simplified version of a query (which is without any type errors). It also returns the results correctly from the DB:
const query = db
// Select all disease mappings
.selectFrom('disease_term_similarity as mapping')
// Append on the source disease's info by it's ID
.leftJoin('disease as src_disease', (join) =>
join.onRef('src_disease.id', '=', 'mapping.source_disease_id')
)
// Append on the target disease's info by it's ID
.leftJoin('disease as tgt_disease', (join) =>
join.onRef('tgt_disease.id', '=', 'mapping.target_disease_id')
);

const results = await query.execute();
const query = db
// Select all disease mappings
.selectFrom('disease_term_similarity as mapping')
// Append on the source disease's info by it's ID
.leftJoin('disease as src_disease', (join) =>
join.onRef('src_disease.id', '=', 'mapping.source_disease_id')
)
// Append on the target disease's info by it's ID
.leftJoin('disease as tgt_disease', (join) =>
join.onRef('tgt_disease.id', '=', 'mapping.target_disease_id')
);

const results = await query.execute();
I noticed that results has the type {}[]. I expected the result to be aware of what fields are contained in the returned objects. Is there something specific I need to do in order to have the results array typed? Or should I be casting it to a type I create myself? Many thanks for your help!!!
Solution:
It looks like the reassignment of query to itself was causing the issue. If I do something like this, the end result has the correct typing: ``` let queryBuilder; ...
Jump to solution
7 Replies
Unknown User
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
Dr. Sauce
Dr. SauceOP•2y ago
Hey @valtyrorn apologies, I made a mistake in simplifying my query for the example above. I edited the post to include that part. The query is all working and returning results sucessfully Oh no, my message was too long 🙂 Here it is:
let query = db
/** Select all disease mappings */
.selectFrom('disease_term_similarity as mapping')
/** Append on the source disease's info by it's ID */
.leftJoin('disease as src_disease', (join) =>
join.onRef('src_disease.id', '=', 'mapping.source_disease_id')
)
/** Append on the target disease's info by it's ID */
.leftJoin('disease as tgt_disease', (join) =>
join.onRef('tgt_disease.id', '=', 'mapping.target_disease_id')
);

query = query.select([
/** Mapping */
'mapping.id',
'mapping.distance',
'mapping.created_at',
'mapping.updated_at',
/** Source disease */
'src_disease.id as src_disease_id',
'src_disease.coding_id as src_disease_coding_id',
'src_disease.coding_id_string as src_disease_coding_id_string',
/** Target disease */
'tgt_disease.id as tgt_disease_id',
'tgt_disease.coding_id as tgt_disease_coding_id',
'tgt_disease.coding_id_string as tgt_disease_coding_id_string'
]);

const results = await query.execute();
let query = db
/** Select all disease mappings */
.selectFrom('disease_term_similarity as mapping')
/** Append on the source disease's info by it's ID */
.leftJoin('disease as src_disease', (join) =>
join.onRef('src_disease.id', '=', 'mapping.source_disease_id')
)
/** Append on the target disease's info by it's ID */
.leftJoin('disease as tgt_disease', (join) =>
join.onRef('tgt_disease.id', '=', 'mapping.target_disease_id')
);

query = query.select([
/** Mapping */
'mapping.id',
'mapping.distance',
'mapping.created_at',
'mapping.updated_at',
/** Source disease */
'src_disease.id as src_disease_id',
'src_disease.coding_id as src_disease_coding_id',
'src_disease.coding_id_string as src_disease_coding_id_string',
/** Target disease */
'tgt_disease.id as tgt_disease_id',
'tgt_disease.coding_id as tgt_disease_coding_id',
'tgt_disease.coding_id_string as tgt_disease_coding_id_string'
]);

const results = await query.execute();
Solution
Dr. Sauce
Dr. Sauce•2y ago
It looks like the reassignment of query to itself was causing the issue. If I do something like this, the end result has the correct typing:
let queryBuilder;

const query = db
/** Select all disease mappings */
.selectFrom('disease_term_similarity as mapping')
/** Append on the source disease's info by it's ID */
.leftJoin('disease as src_disease', (join) =>
join.onRef('src_disease.id', '=', 'mapping.source_disease_id')
)
/** Append on the target disease's info by it's ID */
.leftJoin('disease as tgt_disease', (join) =>
join.onRef('tgt_disease.id', '=', 'mapping.target_disease_id')
);

queryBuilder = query.select([
/** Mapping */
'mapping.id',
'mapping.distance',
'mapping.created_at',
'mapping.updated_at',
/** Source disease */
'src_disease.id as src_disease_id',
'src_disease.coding_id as src_disease_coding_id',
'src_disease.coding_id_string as src_disease_coding_id_string',
/** Target disease */
'tgt_disease.id as tgt_disease_id',
'tgt_disease.coding_id as tgt_disease_coding_id',
'tgt_disease.coding_id_string as tgt_disease_coding_id_string'
]);

const results = await queryBuilder.execute();
let queryBuilder;

const query = db
/** Select all disease mappings */
.selectFrom('disease_term_similarity as mapping')
/** Append on the source disease's info by it's ID */
.leftJoin('disease as src_disease', (join) =>
join.onRef('src_disease.id', '=', 'mapping.source_disease_id')
)
/** Append on the target disease's info by it's ID */
.leftJoin('disease as tgt_disease', (join) =>
join.onRef('tgt_disease.id', '=', 'mapping.target_disease_id')
);

queryBuilder = query.select([
/** Mapping */
'mapping.id',
'mapping.distance',
'mapping.created_at',
'mapping.updated_at',
/** Source disease */
'src_disease.id as src_disease_id',
'src_disease.coding_id as src_disease_coding_id',
'src_disease.coding_id_string as src_disease_coding_id_string',
/** Target disease */
'tgt_disease.id as tgt_disease_id',
'tgt_disease.coding_id as tgt_disease_coding_id',
'tgt_disease.coding_id_string as tgt_disease_coding_id_string'
]);

const results = await queryBuilder.execute();
The above example is slightly contrived. The reason I am using multiple statements to build the query rather than all in one block is because I have several if conditions for which certain parts of the query should or should not be included.
koskimas
koskimas•2y ago
Type of a variable can't change. Reassignments after selects, joins and other method calls that change the query builder type can't work.
Dr. Sauce
Dr. SauceOP•2y ago
Thanks @koskimas what's the best way to add a conditional call onto the query chain? For example, if only in specific cases I want to add an .orderBy call
koskimas
koskimas•2y ago
Only joins, selections and returning method change the type. Others can be reassigned.
Dr. Sauce
Dr. SauceOP•2y ago
I see, so the issue was the line:
query = query.select([
...
query = query.select([
...
Thank you so much for clarifying! Can confirm both of these work 🙂 Thank you! Makes sense now
let queryBuilder;

const query = db
/** Select all disease mappings */
.selectFrom('disease_term_similarity as mapping')
/** Append on the source disease's info by it's ID */
.leftJoin('disease as src_disease', (join) =>
join.onRef('src_disease.id', '=', 'mapping.source_disease_id')
)
/** Append on the target disease's info by it's ID */
.leftJoin('disease as tgt_disease', (join) =>
join.onRef('tgt_disease.id', '=', 'mapping.target_disease_id')
)
.select([
/** Mapping */
'mapping.id',
'mapping.distance',
'mapping.created_at',
'mapping.updated_at',
/** Source disease */
'src_disease.id as src_disease_id',
'src_disease.coding_id as src_disease_coding_id',
'src_disease.coding_id_string as src_disease_coding_id_string',
/** Target disease */
'tgt_disease.id as tgt_disease_id',
'tgt_disease.coding_id as tgt_disease_coding_id',
'tgt_disease.coding_id_string as tgt_disease_coding_id_string'
]);

const results = await query.execute();
let queryBuilder;

const query = db
/** Select all disease mappings */
.selectFrom('disease_term_similarity as mapping')
/** Append on the source disease's info by it's ID */
.leftJoin('disease as src_disease', (join) =>
join.onRef('src_disease.id', '=', 'mapping.source_disease_id')
)
/** Append on the target disease's info by it's ID */
.leftJoin('disease as tgt_disease', (join) =>
join.onRef('tgt_disease.id', '=', 'mapping.target_disease_id')
)
.select([
/** Mapping */
'mapping.id',
'mapping.distance',
'mapping.created_at',
'mapping.updated_at',
/** Source disease */
'src_disease.id as src_disease_id',
'src_disease.coding_id as src_disease_coding_id',
'src_disease.coding_id_string as src_disease_coding_id_string',
/** Target disease */
'tgt_disease.id as tgt_disease_id',
'tgt_disease.coding_id as tgt_disease_coding_id',
'tgt_disease.coding_id_string as tgt_disease_coding_id_string'
]);

const results = await query.execute();
const query = db
/** Select all disease mappings */
.selectFrom('disease_term_similarity as mapping')
/** Append on the source disease's info by it's ID */
.leftJoin('disease as src_disease', (join) =>
join.onRef('src_disease.id', '=', 'mapping.source_disease_id')
)
/** Append on the target disease's info by it's ID */
.leftJoin('disease as tgt_disease', (join) =>
join.onRef('tgt_disease.id', '=', 'mapping.target_disease_id')
);

const queryWithSelect = query.select([
/** Mapping */
'mapping.id',
'mapping.distance',
'mapping.created_at',
'mapping.updated_at',
/** Source disease */
'src_disease.id as src_disease_id',
'src_disease.coding_id as src_disease_coding_id',
'src_disease.coding_id_string as src_disease_coding_id_string',
/** Target disease */
'tgt_disease.id as tgt_disease_id',
'tgt_disease.coding_id as tgt_disease_coding_id',
'tgt_disease.coding_id_string as tgt_disease_coding_id_string'
]);

const results = await queryWithSelect.execute();
const query = db
/** Select all disease mappings */
.selectFrom('disease_term_similarity as mapping')
/** Append on the source disease's info by it's ID */
.leftJoin('disease as src_disease', (join) =>
join.onRef('src_disease.id', '=', 'mapping.source_disease_id')
)
/** Append on the target disease's info by it's ID */
.leftJoin('disease as tgt_disease', (join) =>
join.onRef('tgt_disease.id', '=', 'mapping.target_disease_id')
);

const queryWithSelect = query.select([
/** Mapping */
'mapping.id',
'mapping.distance',
'mapping.created_at',
'mapping.updated_at',
/** Source disease */
'src_disease.id as src_disease_id',
'src_disease.coding_id as src_disease_coding_id',
'src_disease.coding_id_string as src_disease_coding_id_string',
/** Target disease */
'tgt_disease.id as tgt_disease_id',
'tgt_disease.coding_id as tgt_disease_coding_id',
'tgt_disease.coding_id_string as tgt_disease_coding_id_string'
]);

const results = await queryWithSelect.execute();

Did you find this page helpful?