-
Couldn't load subscription status.
- Fork 286
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 when strictNullChecks 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 its hasOne 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 the modelB field in the values argument contain every single field, property, and method of an instance of ModelB. 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 the values argument passed into the create 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 of ModelA's modelB field as partial, but this incorrectly communicates that all fields and columns in ModelBare 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.