- Notifications
You must be signed in to change notification settings - Fork286
Description
Issue
Following methods do not accept an object with an association,
- Model.create()
Versions
"sequelize": "^6.37.6""sequelize-typescript": "^2.1.6"
My tsconfig has no strict mode settings enabled. Interestingly, this problem doesn't occur whenstrictNullChecks is enabled. My tsconfig:
{ "compilerOptions": { "outDir": "./dist", "allowJs": true, "module": "commonjs", "target": "ES2020", "experimentalDecorators": true, "emitDecoratorMetadata": true }, "include": ["./src/**/*"]}Explanation
I am using sequelize and typescript in a project. I am receiving an error when trying to create a new instance of a model while including one of itshasOne associations. Relevant documentation on the matter:https://sequelize.org/docs/v6/advanced-association-concepts/creating-with-associations/.
// Model A export class ModelA extends Model< InferAttributes<ModelA>, InferCreationAttributes<ModelA> > { // ... Other fields/columns, skipping for brevity @HasOne(() => ModelB, { onDelete: "SET NULL" }) modelB: ModelB; }// Model B export class ModelB extends Model< InferAttributes<ModelB>, InferCreationAttributes<ModelB> > { @BelongsTo(() => ModelA) modelA?: ModelA; }And when I try to create an instance of ModelA, including ModelB:
await ModelA.create({...propertiesOfModelA, modelB: {...propertiesOfModelB}}, {include: [ModelB],})I am met with this error:
Type '<fields of modelB argument>' is missing the following properties from type 'ModelB': $add, $set, and 35 more.ts(2740)
ModelA(90, 3): The expected type comes from property 'modelB' which is declared here on type 'Optional<InferCreationAttributes<ModelA, { omit: never; }>, NullishPropertiesOf<InferCreationAttributes<ModelA, { omit: never; }>>>'
I do not expect typescript to enforce that themodelB field in thevalues argument contain every single field, property, and method of an instance ofModelB. I can remove the stricter typing like this:
export class ModelA extends Model {}
But then Typescript has no way to enforce the types inside of thevalues argument passed into thecreate method.
I could typecast, but this feels like a bandaid:
await ModelA.create({...propertiesOfModelA, modelB: {...propertiesOfModelB} as ModelB, {include: [ModelB],})I could also define the type ofModelA'smodelB field as partial, but this incorrectly communicates thatall fields and columns inModelBare optional (even if some are specified as required/not nullable).
@HasOne(() => ModelB, {onDelete: "SET NULL"}) modelB: Partial<ModelB>Even if I were to define ModelB as such, the error persists:
export class ModelB extends Model<Partial<ModelB>> {}
My goal is to maintain type strictness in all relevant model methods (specifically create), so that I can still create models with associations and ensure I'm passing in the correct types.