不要怂,就是干,撸起袖子干!

Commit 9c446f9c by Harry Yu Committed by GitHub

fix(types): fixed types for model.init and sequelize.define; update docs (#12435)

1 parent 54737510
...@@ -13,27 +13,42 @@ In order to avoid installation bloat for non TS users, you must install the foll ...@@ -13,27 +13,42 @@ In order to avoid installation bloat for non TS users, you must install the foll
## Usage ## Usage
Example of a minimal TypeScript project: Example of a minimal TypeScript project with strict type-checking for attributes.
<!--
NOTE!
Keep the following code in sync with `typescriptDocs/ModelInit.ts` to ensure
it typechecks correctly.
-->
```ts ```ts
import { Sequelize, Model, DataTypes, BuildOptions } from 'sequelize'; import {
import { HasManyGetAssociationsMixin, HasManyAddAssociationMixin, HasManyHasAssociationMixin, Association, HasManyCountAssociationsMixin, HasManyCreateAssociationMixin } from 'sequelize'; Sequelize,
Model,
DataTypes,
HasManyGetAssociationsMixin,
HasManyAddAssociationMixin,
HasManyHasAssociationMixin,
Association,
HasManyCountAssociationsMixin,
HasManyCreateAssociationMixin,
Optional,
} from 'sequelize';
// These are the minimum attributes needed to create a User const sequelize = new Sequelize('mysql://root:asd123@localhost:3306/mydb');
interface UserCreationAttributes {
name: string;
preferredName: string | null;
}
// These are all the attributes in the User model // These are all the attributes in the User model
interface UserAttributes extends UserCreationAttributes { interface UserAttributes {
id: number; id: number;
name: string;
preferredName: string | null;
} }
// You can choose to omit the `UserAttributes` and `UserCreationAttributes` // Some attributes are optional in `User.build` and `User.create` calls
// generic types to simplify your types. This will come at the cost of making interface UserCreationAttributes extends Optional<UserAttributes, 'id'> {}
// typechecking slightly less strict.
class User extends Model<UserAttributes, UserCreationAttributes> implements UserAttributes { class User extends Model<UserAttributes, UserCreationAttributes>
implements UserAttributes {
public id!: number; // Note that the `null assertion` `!` is required in strict mode. public id!: number; // Note that the `null assertion` `!` is required in strict mode.
public name!: string; public name!: string;
public preferredName!: string | null; // for nullable fields public preferredName!: string | null; // for nullable fields
...@@ -45,7 +60,6 @@ class User extends Model<UserAttributes, UserCreationAttributes> implements User ...@@ -45,7 +60,6 @@ class User extends Model<UserAttributes, UserCreationAttributes> implements User
// Since TS cannot determine model association at compile time // Since TS cannot determine model association at compile time
// we have to declare them here purely virtually // we have to declare them here purely virtually
// these will not exist until `Model.init` was called. // these will not exist until `Model.init` was called.
public getProjects!: HasManyGetAssociationsMixin<Project>; // Note the null assertions! public getProjects!: HasManyGetAssociationsMixin<Project>; // Note the null assertions!
public addProject!: HasManyAddAssociationMixin<Project, number>; public addProject!: HasManyAddAssociationMixin<Project, number>;
public hasProject!: HasManyHasAssociationMixin<Project, number>; public hasProject!: HasManyHasAssociationMixin<Project, number>;
...@@ -61,18 +75,16 @@ class User extends Model<UserAttributes, UserCreationAttributes> implements User ...@@ -61,18 +75,16 @@ class User extends Model<UserAttributes, UserCreationAttributes> implements User
}; };
} }
const sequelize = new Sequelize('mysql://root:asd123@localhost:3306/mydb'); interface ProjectAttributes {
id: number;
interface ProjectCreationAttributes {
ownerId: number; ownerId: number;
name: string; name: string;
} }
interface ProjectAttributes extends ProjectCreationAttributes { interface ProjectCreationAttributes extends Optional<ProjectAttributes, 'id'> {}
id: number;
}
class Project extends Model<ProjectAttributes, ProjectCreationAttributes> implements ProjectAttributes { class Project extends Model<ProjectAttributes, ProjectCreationAttributes>
implements ProjectAttributes {
public id!: number; public id!: number;
public ownerId!: number; public ownerId!: number;
public name!: string; public name!: string;
...@@ -86,6 +98,8 @@ interface AddressAttributes { ...@@ -86,6 +98,8 @@ interface AddressAttributes {
address: string; address: string;
} }
// You can write `extends Model<AddressAttributes, AddressAttributes>` instead,
// but that will do the exact same thing as below
class Address extends Model<AddressAttributes> implements AddressAttributes { class Address extends Model<AddressAttributes> implements AddressAttributes {
public userId!: number; public userId!: number;
public address!: string; public address!: string;
...@@ -94,7 +108,8 @@ class Address extends Model<AddressAttributes> implements AddressAttributes { ...@@ -94,7 +108,8 @@ class Address extends Model<AddressAttributes> implements AddressAttributes {
public readonly updatedAt!: Date; public readonly updatedAt!: Date;
} }
Project.init({ Project.init(
{
id: { id: {
type: DataTypes.INTEGER.UNSIGNED, type: DataTypes.INTEGER.UNSIGNED,
autoIncrement: true, autoIncrement: true,
...@@ -107,13 +122,16 @@ Project.init({ ...@@ -107,13 +122,16 @@ Project.init({
name: { name: {
type: new DataTypes.STRING(128), type: new DataTypes.STRING(128),
allowNull: false, allowNull: false,
} },
}, { },
{
sequelize, sequelize,
tableName: 'projects', tableName: 'projects',
}); },
);
User.init({ User.init(
{
id: { id: {
type: DataTypes.INTEGER.UNSIGNED, type: DataTypes.INTEGER.UNSIGNED,
autoIncrement: true, autoIncrement: true,
...@@ -125,37 +143,42 @@ User.init({ ...@@ -125,37 +143,42 @@ User.init({
}, },
preferredName: { preferredName: {
type: new DataTypes.STRING(128), type: new DataTypes.STRING(128),
allowNull: true allowNull: true,
} },
}, { },
{
tableName: 'users', tableName: 'users',
sequelize: sequelize, // passing the `sequelize` instance is required sequelize, // passing the `sequelize` instance is required
}); },
);
Address.init({ Address.init(
{
userId: { userId: {
type: DataTypes.INTEGER.UNSIGNED, type: DataTypes.INTEGER.UNSIGNED,
}, },
address: { address: {
type: new DataTypes.STRING(128), type: new DataTypes.STRING(128),
allowNull: false, allowNull: false,
} },
}, { },
{
tableName: 'address', tableName: 'address',
sequelize: sequelize, // passing the `sequelize` instance is required sequelize, // passing the `sequelize` instance is required
}); },
);
// Here we associate which actually populates out pre-declared `association` static and other methods. // Here we associate which actually populates out pre-declared `association` static and other methods.
User.hasMany(Project, { User.hasMany(Project, {
sourceKey: 'id', sourceKey: 'id',
foreignKey: 'ownerId', foreignKey: 'ownerId',
as: 'projects' // this determines the name in `associations`! as: 'projects', // this determines the name in `associations`!
}); });
Address.belongsTo(User, {targetKey: 'id'}); Address.belongsTo(User, { targetKey: 'id' });
User.hasOne(Address,{sourceKey: 'id'}); User.hasOne(Address, { sourceKey: 'id' });
async function stuff() { async function doStuffWithUser() {
const newUser = await User.create({ const newUser = await User.create({
name: 'Johnny', name: 'Johnny',
preferredName: 'John', preferredName: 'John',
...@@ -170,8 +193,66 @@ async function stuff() { ...@@ -170,8 +193,66 @@ async function stuff() {
include: [User.associations.projects], include: [User.associations.projects],
rejectOnEmpty: true, // Specifying true here removes `null` from the return type! rejectOnEmpty: true, // Specifying true here removes `null` from the return type!
}); });
console.log(ourUser.projects![0].name); // Note the `!` null assertion since TS can't know if we included
// Note the `!` null assertion since TS can't know if we included
// the model or not // the model or not
console.log(ourUser.projects![0].name);
}
```
### Usage without strict types for attributes
The typings for Sequelize v5 allowed you to define models without specifying types for the attributes. This is still possible for backwards compatibility and for cases where you feel strict typing for attributes isn't worth it.
<!--
NOTE!
Keep the following code in sync with `typescriptDocs/ModelInitNoAttributes.ts` to ensure
it typechecks correctly.
-->
```ts
import { Sequelize, Model, DataTypes } from 'sequelize';
const sequelize = new Sequelize('mysql://root:asd123@localhost:3306/mydb');
class User extends Model {
public id!: number; // Note that the `null assertion` `!` is required in strict mode.
public name!: string;
public preferredName!: string | null; // for nullable fields
}
User.init(
{
id: {
type: DataTypes.INTEGER.UNSIGNED,
autoIncrement: true,
primaryKey: true,
},
name: {
type: new DataTypes.STRING(128),
allowNull: false,
},
preferredName: {
type: new DataTypes.STRING(128),
allowNull: true,
},
},
{
tableName: 'users',
sequelize, // passing the `sequelize` instance is required
},
);
async function doStuffWithUserModel() {
const newUser = await User.create({
name: 'Johnny',
preferredName: 'John',
});
console.log(newUser.id, newUser.name, newUser.preferredName);
const foundUser = await User.findOne({ where: { name: 'Johnny' } });
if (foundUser === null) return;
console.log(foundUser.name);
} }
``` ```
...@@ -179,53 +260,82 @@ async function stuff() { ...@@ -179,53 +260,82 @@ async function stuff() {
In Sequelize versions before v5, the default way of defining a model involved using `sequelize.define`. It's still possible to define models with that, and you can also add typings to these models using interfaces. In Sequelize versions before v5, the default way of defining a model involved using `sequelize.define`. It's still possible to define models with that, and you can also add typings to these models using interfaces.
<!--
NOTE!
Keep the following code in sync with `typescriptDocs/Define.ts` to ensure
it typechecks correctly.
-->
```ts ```ts
import { Sequelize, Model, DataTypes, Optional } from 'sequelize';
const sequelize = new Sequelize('mysql://root:asd123@localhost:3306/mydb');
// We recommend you declare an interface for the attributes, for stricter typechecking // We recommend you declare an interface for the attributes, for stricter typechecking
interface MyModelAttributes { interface UserAttributes {
readonly id: number; id: number;
name: string; name: string;
} }
interface MyModelCreationAttributes extends Optional<MyModelAttributes, 'id'> {} // Some fields are optional when calling UserModel.create() or UserModel.build()
interface UserCreationAttributes extends Optional<UserAttributes, 'id'> {}
// We need to declare an interface for our model that is basically what our class would be // We need to declare an interface for our model that is basically what our class would be
interface MyModel extends Model<MyModelAttributes, MyModelCreationAttributes>, MyModelAttributes {} interface UserInstance
extends Model<UserAttributes, UserCreationAttributes>,
UserAttributes {}
const MyDefineModel = sequelize.define<MyModel>('MyDefineModel', { const UserModel = sequelize.define<UserInstance>('User', {
id: { id: {
primaryKey: true, primaryKey: true,
type: DataTypes.INTEGER.UNSIGNED, type: DataTypes.INTEGER.UNSIGNED,
},
name: {
type: DataTypes.STRING,
} }
}); });
async function stuffTwo() { async function doStuff() {
const myModel = await MyDefineModel.findByPk(1, { const instance = await UserModel.findByPk(1, {
rejectOnEmpty: true, rejectOnEmpty: true,
}); });
console.log(myModel.id); console.log(instance.id);
} }
``` ```
If you're comfortable with somewhat less strict typing for the attributes on a model, you can save some code by defining the Instance to just extend `Model` without any attributes in the generic types. If you're comfortable with somewhat less strict typing for the attributes on a model, you can save some code by defining the Instance to just extend `Model` without any attributes in the generic types.
<!--
NOTE!
Keep the following code in sync with `typescriptDocs/DefineNoAttributes.ts` to ensure
it typechecks correctly.
-->
```ts ```ts
import { Sequelize, Model, DataTypes } from 'sequelize';
const sequelize = new Sequelize('mysql://root:asd123@localhost:3306/mydb');
// We need to declare an interface for our model that is basically what our class would be // We need to declare an interface for our model that is basically what our class would be
interface MyModel extends Model { interface UserInstance extends Model {
readonly id: number; id: number;
name: string; name: string;
} }
const MyDefineModel = sequelize.define<MyModel>('MyDefineModel', { const UserModel = sequelize.define<UserInstance>('User', {
id: { id: {
primaryKey: true, primaryKey: true,
type: DataTypes.INTEGER.UNSIGNED, type: DataTypes.INTEGER.UNSIGNED,
} },
name: {
type: DataTypes.STRING,
},
}); });
async function stuffTwo() { async function doStuff() {
const myModel = await MyDefineModel.findByPk(1, { const instance = await UserModel.findByPk(1, {
rejectOnEmpty: true, rejectOnEmpty: true,
}); });
console.log(myModel.id); console.log(instance.id);
} }
``` ```
...@@ -1633,7 +1633,7 @@ export abstract class Model<TModelAttributes extends {} = any, TCreationAttribut ...@@ -1633,7 +1633,7 @@ export abstract class Model<TModelAttributes extends {} = any, TCreationAttribut
*/ */
public static init<M extends Model>( public static init<M extends Model>(
this: ModelStatic<M>, this: ModelStatic<M>,
attributes: ModelAttributes<M, M['_creationAttributes']>, options: InitOptions<M> attributes: ModelAttributes<M, M['_attributes']>, options: InitOptions<M>
): Model; ): Model;
/** /**
......
...@@ -772,7 +772,7 @@ export class Sequelize extends Hooks { ...@@ -772,7 +772,7 @@ export class Sequelize extends Hooks {
* A hook that is run before sequelize.sync call * A hook that is run before sequelize.sync call
* @param fn A callback function that is called with options passed to sequelize.sync * @param fn A callback function that is called with options passed to sequelize.sync
*/ */
public static beforeBulkSync(name: string, fn: (options: SyncOptions) => HookReturn): void; public static beforeBulkSync(dname: string, fn: (options: SyncOptions) => HookReturn): void;
public static beforeBulkSync(fn: (options: SyncOptions) => HookReturn): void; public static beforeBulkSync(fn: (options: SyncOptions) => HookReturn): void;
/** /**
...@@ -1164,7 +1164,7 @@ export class Sequelize extends Hooks { ...@@ -1164,7 +1164,7 @@ export class Sequelize extends Hooks {
* @param options These options are merged with the default define options provided to the Sequelize * @param options These options are merged with the default define options provided to the Sequelize
* constructor * constructor
*/ */
public define<M extends Model, TCreationAttributes = M['_creationAttributes']>( public define<M extends Model, TCreationAttributes = M['_attributes']>(
modelName: string, modelName: string,
attributes: ModelAttributes<M, TCreationAttributes>, attributes: ModelAttributes<M, TCreationAttributes>,
options?: ModelOptions options?: ModelOptions
......
import { BuildOptions, DataTypes, Model } from 'sequelize'; import { BuildOptions, DataTypes, Model, Optional } from 'sequelize';
import { sequelize } from './connection'; import { sequelize } from './connection';
// I really wouldn't recommend this, but if you want you can still use define() and interfaces // I really wouldn't recommend this, but if you want you can still use define() and interfaces
...@@ -8,16 +8,24 @@ interface UserAttributes { ...@@ -8,16 +8,24 @@ interface UserAttributes {
username: string; username: string;
firstName: string; firstName: string;
lastName: string; lastName: string;
createdAt: Date;
updatedAt: Date;
} }
interface UserCreationAttributes extends Partial<UserAttributes> {} interface UserCreationAttributes extends Optional<UserAttributes, 'id'> {}
interface UserModel extends Model<UserAttributes, UserCreationAttributes>, UserAttributes {} interface UserModel
extends Model<UserAttributes, UserCreationAttributes>,
UserAttributes {}
const User = sequelize.define<UserModel>( const User = sequelize.define<UserModel>(
'User', { firstName: DataTypes.STRING }, { tableName: 'users' }); 'User',
{
id: { type: DataTypes.NUMBER, primaryKey: true },
username: DataTypes.STRING,
firstName: DataTypes.STRING,
lastName: DataTypes.STRING,
},
{ tableName: 'users' },
);
async function test() { async function test() {
const user: UserModel = new User() as UserModel; const user: UserModel = new User() as UserModel;
...@@ -36,9 +44,17 @@ interface UntypedUserModel extends Model, UserAttributes {} ...@@ -36,9 +44,17 @@ interface UntypedUserModel extends Model, UserAttributes {}
type UntypedUserModelStatic = typeof Model & { type UntypedUserModelStatic = typeof Model & {
new (values?: keyof any, options?: BuildOptions): UntypedUserModel; new (values?: keyof any, options?: BuildOptions): UntypedUserModel;
customStaticMethod(): unknown; customStaticMethod(): unknown;
} };
const UntypedUser = sequelize.define<UntypedUserModel>( const UntypedUser = sequelize.define<UntypedUserModel>(
'User', { firstName: DataTypes.STRING }, { tableName: 'users' }) as UntypedUserModelStatic; 'User',
{
id: { type: DataTypes.NUMBER, primaryKey: true },
username: DataTypes.STRING,
firstName: DataTypes.STRING,
lastName: DataTypes.STRING,
},
{ tableName: 'users' },
) as UntypedUserModelStatic;
UntypedUser.customStaticMethod = () => {}; UntypedUser.customStaticMethod = () => {};
......
...@@ -21,8 +21,8 @@ export interface UserAttributes { ...@@ -21,8 +21,8 @@ export interface UserAttributes {
} }
/** /**
* In this case, we make every single field optional. In real cases, only * In this case, we make most fields optional. In real cases,
* fields that have default/autoincrement values should be made optional. * only fields that have default/autoincrement values should be made optional.
*/ */
export interface UserCreationAttributes extends Optional<UserAttributes, 'id' | 'username' | 'lastName' | 'groupId'> {} export interface UserCreationAttributes extends Optional<UserAttributes, 'id' | 'username' | 'lastName' | 'groupId'> {}
...@@ -48,6 +48,10 @@ export class User extends Model<UserAttributes, UserCreationAttributes> implemen ...@@ -48,6 +48,10 @@ export class User extends Model<UserAttributes, UserCreationAttributes> implemen
User.init( User.init(
{ {
id: {
type: DataTypes.NUMBER,
primaryKey: true,
},
firstName: DataTypes.STRING, firstName: DataTypes.STRING,
lastName: DataTypes.STRING, lastName: DataTypes.STRING,
username: DataTypes.STRING, username: DataTypes.STRING,
...@@ -62,7 +66,7 @@ User.init( ...@@ -62,7 +66,7 @@ User.init(
}, },
setterMethods: { setterMethods: {
b(val: string) { b(val: string) {
(<User>this).username = val; this.username = val;
}, },
}, },
scopes: { scopes: {
......
/**
* Keep this file in sync with the code in the "Usage of `sequelize.define`"
* section in typescript.md
*/
import { Sequelize, Model, DataTypes, Optional } from 'sequelize';
const sequelize = new Sequelize('mysql://root:asd123@localhost:3306/mydb');
// We recommend you declare an interface for the attributes, for stricter typechecking
interface UserAttributes {
id: number;
name: string;
}
// Some fields are optional when calling UserModel.create() or UserModel.build()
interface UserCreationAttributes extends Optional<UserAttributes, 'id'> {}
// We need to declare an interface for our model that is basically what our class would be
interface UserInstance
extends Model<UserAttributes, UserCreationAttributes>,
UserAttributes {}
const UserModel = sequelize.define<UserInstance>('User', {
id: {
primaryKey: true,
type: DataTypes.INTEGER.UNSIGNED,
},
name: {
type: DataTypes.STRING,
}
});
async function doStuff() {
const instance = await UserModel.findByPk(1, {
rejectOnEmpty: true,
});
console.log(instance.id);
}
/**
* Keep this file in sync with the code in the "Usage of `sequelize.define`"
* that doesn't have attribute types in typescript.md
*/
import { Sequelize, Model, DataTypes } from 'sequelize';
const sequelize = new Sequelize('mysql://root:asd123@localhost:3306/mydb');
// We need to declare an interface for our model that is basically what our class would be
interface UserInstance extends Model {
id: number;
name: string;
}
const UserModel = sequelize.define<UserInstance>('User', {
id: {
primaryKey: true,
type: DataTypes.INTEGER.UNSIGNED,
},
name: {
type: DataTypes.STRING,
},
});
async function doStuff() {
const instance = await UserModel.findByPk(1, {
rejectOnEmpty: true,
});
console.log(instance.id);
}
/**
* Keep this file in sync with the code in the "Usage" section in typescript.md
*/
import {
Sequelize,
Model,
DataTypes,
HasManyGetAssociationsMixin,
HasManyAddAssociationMixin,
HasManyHasAssociationMixin,
Association,
HasManyCountAssociationsMixin,
HasManyCreateAssociationMixin,
Optional,
} from 'sequelize';
const sequelize = new Sequelize('mysql://root:asd123@localhost:3306/mydb');
// These are all the attributes in the User model
interface UserAttributes {
id: number;
name: string;
preferredName: string | null;
}
// Some attributes are optional in `User.build` and `User.create` calls
interface UserCreationAttributes extends Optional<UserAttributes, 'id'> {}
class User extends Model<UserAttributes, UserCreationAttributes>
implements UserAttributes {
public id!: number; // Note that the `null assertion` `!` is required in strict mode.
public name!: string;
public preferredName!: string | null; // for nullable fields
// timestamps!
public readonly createdAt!: Date;
public readonly updatedAt!: Date;
// Since TS cannot determine model association at compile time
// we have to declare them here purely virtually
// these will not exist until `Model.init` was called.
public getProjects!: HasManyGetAssociationsMixin<Project>; // Note the null assertions!
public addProject!: HasManyAddAssociationMixin<Project, number>;
public hasProject!: HasManyHasAssociationMixin<Project, number>;
public countProjects!: HasManyCountAssociationsMixin;
public createProject!: HasManyCreateAssociationMixin<Project>;
// You can also pre-declare possible inclusions, these will only be populated if you
// actively include a relation.
public readonly projects?: Project[]; // Note this is optional since it's only populated when explicitly requested in code
public static associations: {
projects: Association<User, Project>;
};
}
interface ProjectAttributes {
id: number;
ownerId: number;
name: string;
}
interface ProjectCreationAttributes extends Optional<ProjectAttributes, 'id'> {}
class Project extends Model<ProjectAttributes, ProjectCreationAttributes>
implements ProjectAttributes {
public id!: number;
public ownerId!: number;
public name!: string;
public readonly createdAt!: Date;
public readonly updatedAt!: Date;
}
interface AddressAttributes {
userId: number;
address: string;
}
// You can write `extends Model<AddressAttributes, AddressAttributes>` instead,
// but that will do the exact same thing as below
class Address extends Model<AddressAttributes> implements AddressAttributes {
public userId!: number;
public address!: string;
public readonly createdAt!: Date;
public readonly updatedAt!: Date;
}
Project.init(
{
id: {
type: DataTypes.INTEGER.UNSIGNED,
autoIncrement: true,
primaryKey: true,
},
ownerId: {
type: DataTypes.INTEGER.UNSIGNED,
allowNull: false,
},
name: {
type: new DataTypes.STRING(128),
allowNull: false,
},
},
{
sequelize,
tableName: 'projects',
},
);
User.init(
{
id: {
type: DataTypes.INTEGER.UNSIGNED,
autoIncrement: true,
primaryKey: true,
},
name: {
type: new DataTypes.STRING(128),
allowNull: false,
},
preferredName: {
type: new DataTypes.STRING(128),
allowNull: true,
},
},
{
tableName: 'users',
sequelize, // passing the `sequelize` instance is required
},
);
Address.init(
{
userId: {
type: DataTypes.INTEGER.UNSIGNED,
},
address: {
type: new DataTypes.STRING(128),
allowNull: false,
},
},
{
tableName: 'address',
sequelize, // passing the `sequelize` instance is required
},
);
// Here we associate which actually populates out pre-declared `association` static and other methods.
User.hasMany(Project, {
sourceKey: 'id',
foreignKey: 'ownerId',
as: 'projects', // this determines the name in `associations`!
});
Address.belongsTo(User, { targetKey: 'id' });
User.hasOne(Address, { sourceKey: 'id' });
async function doStuffWithUser() {
const newUser = await User.create({
name: 'Johnny',
preferredName: 'John',
});
console.log(newUser.id, newUser.name, newUser.preferredName);
const project = await newUser.createProject({
name: 'first!',
});
const ourUser = await User.findByPk(1, {
include: [User.associations.projects],
rejectOnEmpty: true, // Specifying true here removes `null` from the return type!
});
// Note the `!` null assertion since TS can't know if we included
// the model or not
console.log(ourUser.projects![0].name);
}
/**
* Keep this file in sync with the code in the "Usage without strict types for
* attributes" section in typescript.md
*/
import { Sequelize, Model, DataTypes } from 'sequelize';
const sequelize = new Sequelize('mysql://root:asd123@localhost:3306/mydb');
class User extends Model {
public id!: number; // Note that the `null assertion` `!` is required in strict mode.
public name!: string;
public preferredName!: string | null; // for nullable fields
}
User.init(
{
id: {
type: DataTypes.INTEGER.UNSIGNED,
autoIncrement: true,
primaryKey: true,
},
name: {
type: new DataTypes.STRING(128),
allowNull: false,
},
preferredName: {
type: new DataTypes.STRING(128),
allowNull: true,
},
},
{
tableName: 'users',
sequelize, // passing the `sequelize` instance is required
},
);
async function doStuffWithUserModel() {
const newUser = await User.create({
name: 'Johnny',
preferredName: 'John',
});
console.log(newUser.id, newUser.name, newUser.preferredName);
const foundUser = await User.findOne({ where: { name: 'Johnny' } });
if (foundUser === null) return;
console.log(foundUser.name);
}
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!