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

Commit 04e3592e by Simon Schick Committed by GitHub

docs: misc improvements for TS, best practises for classes and changelog fixes (#10850)

1 parent ba5192ce
...@@ -805,14 +805,8 @@ Image.init({ ...@@ -805,14 +805,8 @@ Image.init({
link: Sequelize.STRING link: Sequelize.STRING
}, { sequelize, modelName: 'image' }); }, { sequelize, modelName: 'image' });
class Comment extends Model {} class Comment extends Model {
Comment.init({ getItem(options) {
title: Sequelize.STRING,
commentable: Sequelize.STRING,
commentableId: Sequelize.INTEGER
}, { sequelize, modelName: 'comment' });
Comment.prototype.getItem = function(options) {
return this[ return this[
'get' + 'get' +
this.get('commentable') this.get('commentable')
...@@ -820,7 +814,14 @@ Comment.prototype.getItem = function(options) { ...@@ -820,7 +814,14 @@ Comment.prototype.getItem = function(options) {
.toUpperCase() + .toUpperCase() +
this.get('commentable').substr(1) this.get('commentable').substr(1)
](options); ](options);
}; }
}
Comment.init({
title: Sequelize.STRING,
commentable: Sequelize.STRING,
commentableId: Sequelize.INTEGER
}, { sequelize, modelName: 'comment' });
Post.hasMany(Comment, { Post.hasMany(Comment, {
foreignKey: 'commentableId', foreignKey: 'commentableId',
......
...@@ -651,29 +651,29 @@ sequelize.sync({ force: true, match: /_test$/ }); ...@@ -651,29 +651,29 @@ sequelize.sync({ force: true, match: /_test$/ });
Sequelize Models are ES6 classes. You can very easily add custom instance or class level methods. Sequelize Models are ES6 classes. You can very easily add custom instance or class level methods.
```js ```js
class User extends Model {} class User extends Model {
User.init({ firstname: Sequelize.STRING }, { sequelize }); // Adding a class level method
static classLevelMethod() {
// Adding a class level method
User.classLevelMethod = function() {
return 'foo'; return 'foo';
}; }
// Adding an instance level method // Adding an instance level method
User.prototype.instanceLevelMethod = function() { instanceLevelMethod() {
return 'bar'; return 'bar';
}; }
}
User.init({ firstname: Sequelize.STRING }, { sequelize });
``` ```
Of course you can also access the instance's data and generate virtual getters: Of course you can also access the instance's data and generate virtual getters:
```js ```js
class User extends Model {} class User extends Model {
User.init({ firstname: Sequelize.STRING, lastname: Sequelize.STRING }, { sequelize }); getFullname() {
User.prototype.getFullname = function() {
return [this.firstname, this.lastname].join(' '); return [this.firstname, this.lastname].join(' ');
}; }
}
User.init({ firstname: Sequelize.STRING, lastname: Sequelize.STRING }, { sequelize });
// Example: // Example:
User.build({ firstname: 'foo', lastname: 'bar' }).getFullname() // 'foo bar' User.build({ firstname: 'foo', lastname: 'bar' }).getFullname() // 'foo bar'
......
...@@ -33,15 +33,15 @@ class User extends Model { ...@@ -33,15 +33,15 @@ class User extends Model {
// 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>; 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>;
public countProjects: HasManyCountAssociationsMixin; public countProjects!: HasManyCountAssociationsMixin;
public createProject: HasManyCreateAssociationMixin<Project>; public createProject!: HasManyCreateAssociationMixin<Project>;
// You can also pre-declare possible inclusions, these will only be populated if you // You can also pre-declare possible inclusions, these will only be populated if you
// actively include a relation. // actively include a relation.
public readonly projects?: Project[]; public readonly projects?: Project[]; // Note this is optional since it's only populated when explicitly requested in code
public static associations: { public static associations: {
projects: Association<User, Project>; projects: Association<User, Project>;
...@@ -59,14 +59,22 @@ class Project extends Model { ...@@ -59,14 +59,22 @@ class Project extends Model {
public readonly updatedAt!: Date; public readonly updatedAt!: Date;
} }
class Address extends Model {
public userId!: number;
public address!: string;
public readonly createdAt!: Date;
public readonly updatedAt!: Date;
}
Project.init({ Project.init({
id: { id: {
type: new DataTypes.INTEGER.UNSIGNED(), // you can omit the `new` but this is discouraged type: DataTypes.INTEGER.UNSIGNED, // you can omit the `new` but this is discouraged
autoIncrement: true, autoIncrement: true,
primaryKey: true, primaryKey: true,
}, },
ownerId: { ownerId: {
type: new DataTypes.INTEGER.UNSIGNED(), type: DataTypes.INTEGER.UNSIGNED,
allowNull: false, allowNull: false,
}, },
name: { name: {
...@@ -80,7 +88,7 @@ Project.init({ ...@@ -80,7 +88,7 @@ Project.init({
User.init({ User.init({
id: { id: {
type: new DataTypes.INTEGER.UNSIGNED(), type: DataTypes.INTEGER.UNSIGNED,
autoIncrement: true, autoIncrement: true,
primaryKey: true, primaryKey: true,
}, },
...@@ -94,16 +102,32 @@ User.init({ ...@@ -94,16 +102,32 @@ User.init({
} }
}, { }, {
tableName: 'users', tableName: 'users',
modelName: 'user', sequelize: sequelize, // this bit is important
});
Address.init({
userId: {
type: DataTypes.INTEGER.UNSIGNED,
},
address: {
type: new DataTypes.STRING(128),
allowNull: false,
}
}, {
tableName: 'users',
sequelize: sequelize, // this bit is important sequelize: sequelize, // this bit is important
}); });
// 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',
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'});
User.hasOne(Address,{sourceKey: 'id'});
async function stuff() { async function stuff() {
// Please note that when using async/await you lose the `bluebird` promise context // Please note that when using async/await you lose the `bluebird` promise context
// and you fall back to native // and you fall back to native
...@@ -118,7 +142,7 @@ async function stuff() { ...@@ -118,7 +142,7 @@ async function stuff() {
}); });
const ourUser = await User.findByPk(1, { const ourUser = await User.findByPk(1, {
include: [User.associations.Project], 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 console.log(ourUser.projects![0].name); // Note the `!` null assertion since TS can't know if we included
...@@ -137,12 +161,11 @@ interface MyModel extends Model { ...@@ -137,12 +161,11 @@ interface MyModel extends Model {
} }
// Need to declare the static model so `findOne` etc. use correct types. // Need to declare the static model so `findOne` etc. use correct types.
// You can also declare all your association stuff in here
type MyModelStatic = typeof Model & { type MyModelStatic = typeof Model & {
new (values?: object, options?: BuildOptions): MyModel; new (values?: object, options?: BuildOptions): MyModel;
} }
// TS can't derive a proper class definition from a `.define` call, therefore we need to cast here. // TS can't derive a proper class definition from a `.define` call, therefor we need to cast here.
const MyDefineModel = <MyModelStatic>sequelize.define('MyDefineModel', { const MyDefineModel = <MyModelStatic>sequelize.define('MyDefineModel', {
id: { id: {
primaryKey: true, primaryKey: true,
...@@ -158,4 +181,5 @@ function stuffTwo() { ...@@ -158,4 +181,5 @@ function stuffTwo() {
console.log(myModel.id); console.log(myModel.id);
}); });
} }
``` ```
...@@ -172,6 +172,10 @@ Model.findAll({ ...@@ -172,6 +172,10 @@ Model.findAll({
### Query Interface ### Query Interface
- `changeColumn` no longer generates constraint with `_idx` suffix. Now Sequelize does not specify any name for constraints thus defaulting to database engine naming. This aligns behavior of `sync`, `createTable` and `changeColumn`. - `changeColumn` no longer generates constraint with `_idx` suffix. Now Sequelize does not specify any name for constraints thus defaulting to database engine naming. This aligns behavior of `sync`, `createTable` and `changeColumn`.
- `addIndex` aliases options aliases have been removed, use the following instead.
- `indexName` => `name`
- `indicesType` => `type`
- `indexType`/`method` => `using`
### Others ### Others
......
...@@ -24,15 +24,15 @@ class User extends Model { ...@@ -24,15 +24,15 @@ class User extends Model {
// 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>; 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>;
public countProjects: HasManyCountAssociationsMixin; public countProjects!: HasManyCountAssociationsMixin;
public createProject: HasManyCreateAssociationMixin<Project>; public createProject!: HasManyCreateAssociationMixin<Project>;
// You can also pre-declare possible inclusions, these will only be populated if you // You can also pre-declare possible inclusions, these will only be populated if you
// actively include a relation. // actively include a relation.
public readonly projects?: Project[]; public readonly projects?: Project[]; // Note this is optional since it's only populated when explicitly requested in code
public static associations: { public static associations: {
projects: Association<User, Project>; projects: Association<User, Project>;
...@@ -60,12 +60,12 @@ class Address extends Model { ...@@ -60,12 +60,12 @@ class Address extends Model {
Project.init({ Project.init({
id: { id: {
type: new DataTypes.INTEGER.UNSIGNED(), // you can omit the `new` but this is discouraged type: DataTypes.INTEGER.UNSIGNED, // you can omit the `new` but this is discouraged
autoIncrement: true, autoIncrement: true,
primaryKey: true, primaryKey: true,
}, },
ownerId: { ownerId: {
type: new DataTypes.INTEGER.UNSIGNED(), type: DataTypes.INTEGER.UNSIGNED,
allowNull: false, allowNull: false,
}, },
name: { name: {
...@@ -79,7 +79,7 @@ Project.init({ ...@@ -79,7 +79,7 @@ Project.init({
User.init({ User.init({
id: { id: {
type: new DataTypes.INTEGER.UNSIGNED(), type: DataTypes.INTEGER.UNSIGNED,
autoIncrement: true, autoIncrement: true,
primaryKey: true, primaryKey: true,
}, },
...@@ -98,7 +98,7 @@ User.init({ ...@@ -98,7 +98,7 @@ User.init({
Address.init({ Address.init({
userId: { userId: {
type: new DataTypes.INTEGER.UNSIGNED(), type: DataTypes.INTEGER.UNSIGNED,
}, },
address: { address: {
type: new DataTypes.STRING(128), type: new DataTypes.STRING(128),
......
import { Association, HasOne, Model, Sequelize } from 'sequelize'; import { Association, HasOne, Model, Sequelize } from 'sequelize';
class MyModel extends Model { class MyModel extends Model {
public num: number; public num!: number;
public static associations: { public static associations: {
other: HasOne; other: HasOne;
}; };
......
...@@ -15,19 +15,19 @@ export class User extends Model { ...@@ -15,19 +15,19 @@ export class User extends Model {
group: BelongsTo<User, UserGroup>; group: BelongsTo<User, UserGroup>;
}; };
public id: number; public id!: number;
public username: string; public username!: string;
public firstName: string; public firstName!: string;
public lastName: string; public lastName!: string;
public createdAt: Date; public createdAt!: Date;
public updatedAt: Date; public updatedAt!: Date;
// mixins for association (optional) // mixins for association (optional)
public groupId: number; public groupId!: number;
public group: UserGroup; public group?: UserGroup;
public getGroup: BelongsToGetAssociationMixin<UserGroup>; public getGroup!: BelongsToGetAssociationMixin<UserGroup>;
public setGroup: BelongsToSetAssociationMixin<UserGroup, number>; public setGroup!: BelongsToSetAssociationMixin<UserGroup, number>;
public createGroup: BelongsToCreateAssociationMixin<UserGroup>; public createGroup!: BelongsToCreateAssociationMixin<UserGroup>;
} }
User.init( User.init(
......
...@@ -19,20 +19,20 @@ export class UserGroup extends Model { ...@@ -19,20 +19,20 @@ export class UserGroup extends Model {
users: HasMany<UserGroup, User> users: HasMany<UserGroup, User>
}; };
public id: number; public id!: number;
public name: string; public name!: string;
// mixins for association (optional) // mixins for association (optional)
public users: User[]; public users!: User[];
public getUsers: HasManyGetAssociationsMixin<User>; public getUsers!: HasManyGetAssociationsMixin<User>;
public setUsers: HasManySetAssociationsMixin<User, number>; public setUsers!: HasManySetAssociationsMixin<User, number>;
public addUser: HasManyAddAssociationMixin<User, number>; public addUser!: HasManyAddAssociationMixin<User, number>;
public addUsers: HasManyAddAssociationsMixin<User, number>; public addUsers!: HasManyAddAssociationsMixin<User, number>;
public createUser: HasManyCreateAssociationMixin<number>; public createUser!: HasManyCreateAssociationMixin<number>;
public countUsers: HasManyCountAssociationsMixin; public countUsers!: HasManyCountAssociationsMixin;
public hasUser: HasManyHasAssociationMixin<User, number>; public hasUser!: HasManyHasAssociationMixin<User, number>;
public removeUser: HasManyRemoveAssociationMixin<User, number>; public removeUser!: HasManyRemoveAssociationMixin<User, number>;
public removeUsers: HasManyRemoveAssociationsMixin<User, number>; public removeUsers!: HasManyRemoveAssociationsMixin<User, number>;
} }
// attach all the metadata to the model // attach all the metadata to the model
......
...@@ -3,10 +3,7 @@ ...@@ -3,10 +3,7 @@
"module": "commonjs", "module": "commonjs",
"target": "es6", "target": "es6",
"noEmit": true, "noEmit": true,
"noImplicitAny": true, "strict": true,
"noImplicitThis": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"sequelize": ["../"], "sequelize": ["../"],
......
...@@ -2,7 +2,7 @@ import { AndOperator, fn, Model, Op, OrOperator, Sequelize, WhereOperators, Wher ...@@ -2,7 +2,7 @@ import { AndOperator, fn, Model, Op, OrOperator, Sequelize, WhereOperators, Wher
import Transaction from '../lib/transaction'; import Transaction from '../lib/transaction';
class MyModel extends Model { class MyModel extends Model {
public hi: number; public hi!: number;
} }
let where: WhereOptions; let where: WhereOptions;
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!