How to Handle Sequelize and Typescript like the Gods meant to!

troll

I do not have anything a gains the LEGACY decorators, but I just don’t like the 💩 they leave once you bundle the code it almost looks like PHP Code 😆 I’m joking I ❤️ Php in fact the most beautiful thing that I love of PHP is the fact that I have not ever used it b4. well let’s begin with this thing.

Photo by Bernard Hermant on Unsplash

As always we first need to have a typescript project. so let us create our own.

$ npm init -y

that will generate a package.json with default values. Time to install dependencies

$ npm i express body-parser cors sequelize pg-hstore pg

As some of those repos don’t care about types. we need to get them types from @types

$ npm i -D @types/node @types/express @types/body-parser @types/cors @types/bluebird typescript tslib

We also install typescript and tslib.

at the root of your project create a folder call types

The name of the subfolders depend on you, but I always have a lib.d.ts file, thats where I usually set my env variables

/// <reference types="node" />
/// <reference types="express" />
declare namespace NodeJS {
interface ProcessEnv {
readonly
NODE_ENV: "development" | "production" | "test";
readonly PUBLIC_URL: string;
readonly SERVER_DB_USER: string;
readonly SERVER_DB_PASSWORD: string;
readonly SERVER_DB_NAME: string;
readonly SERVER_DB_HOST: string;
readonly SERVER_DB_PORT: string;
readonly SERVER_DIALET: "mysql" | "postgres" | "sqlite" | "mariadb" | "mssql" | undefined;
}
}

then inside types folder add a sub folder name it whatever you feel like: mine will be eneto-models.

and inside of it create an index.d.ts file

in it we are going to declare our module.

the name of the module does not have to match the name of the folder, but if it can have the same name, always go for it, I’ll just use a different name for the purpose of showing that it does not have to have the same name as my folder is call eneto-models and the module inside is call @eneto/models.

interface BaseAttributes {
id: number;
createdAt: Date;
updatedAt: Date;
}

as every single table is going to have those three columns and as I do not want to write them more than once I put them in side an interface

Now let’s create our users “table”

interface UserAttributtes extends BaseAttributes {
name: string;
lastName: string;
email: string;
}

it might look like it only contains those three attributes, but in reality

it has 6

import * as Bluebird from "bluebird";
import { BuildOptions, Model, Sequelize } from "sequelize";

At the very top import those types.

It’s time to add the two lil boys that will make the magic.

interface Entity<T> extends Model<T, T> {
// If you have the eslint rule that no interface can be empty uncomment those three :3
// id: number;
// createdAt: Date;
// updatedAt: Date;
}type Repository<T> = typeof Model & {
new (values?: object, options?: BuildOptions): Entity<T>;
};

Now all you need to do on your actual code is to use those types. if by any means typescript cries because it is not able to find your types open your tsconfig.json

.....
"moduleResolution": "node",
"baseUrl": "./node_modules",
"paths": {
"*": [
"./*",
"./@types/*",
"../types/*"
],
/*name of your module mine was @eneto/models*/
"@eneto/models": [
/*name of the path*/
"../types/eneto-models/*"
]
},
....

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store