-
Notifications
You must be signed in to change notification settings - Fork 3
tnex overview
7sempra edited this page Jun 5, 2017
·
23 revisions
We interact with the database via Tnex
, a typesafe wrapper around Knex. Tnex supports most of the same functions as Knex, which a few differences to ensure type safety (detailed below).
The basic idea behind Tnex is that each table in your database is represented by a Typescript class. This class defines the table's schema. Tnex then enforces that all of your DB operations are compatible with that schema.
Each table is represented by a Typescript class. A table declaration has three parts:
// tables.ts
// 1. Declare class. Defines table's schema.
export class Dog {
dog_id = number(); // Column named "id" with a number type
dog_name = string();
dog_owner = nullable(number());
}
// 2. Create instance. Used when calling tnex functions.
export const dog = new Dog();
// 3. Register table. Associates schema with table name
register('dog', dog);
- Each class property defines a column in the table.
- Each property must be prefixed with the same table prefix. You can choose whatever prefix you want, as long as it's globally unique among your table classes.
- The prefixes should only appear in your class definitions; they shouldn't be part of your actual column names.
- Note the use of the
nullable()
function to define a nullable column.
import { dog } from './tables';
import { Tnex, val } from './tnex';
function getOwnedDogs(db: Tnex, owner: number) {
return db
.select(dog)
.columns(
'dog_id',
'dog_name',
)
.where('dog_owner', '=', val(owner))
.run();
}
Notes:
- Unlike with Knex, we use the
columns()
function to specify which columns we want to select. - Note the use of
val()
when comparing to a - We have to call
run()
when we've completed our call chain (or we won't get a Promise back). - Typescript will automatically infer the return type for us, so we usually don't need to specify one. It can sometimes be convenient to declare that a db function returns a specific interface, though.
- The inferred return type of this function is
Promise<Pick<Dog, 'dog_id'|'dog_name'>>
. ThePromise<>
part should be familiar.Pick<T, K>
means "given an interface T, return a subset of it that includes just the keys K". SoPick<Dog, 'dog_id'|'dog_name'>
is equivalent to{ dog_id: number, dog_name: string }
.