diff --git a/src/common/DeepPartial.ts b/src/common/DeepPartial.ts index 730000377d..a241f81bed 100644 --- a/src/common/DeepPartial.ts +++ b/src/common/DeepPartial.ts @@ -1,8 +1,12 @@ /** * Same as Partial but goes deeper and makes Partial all its properties and sub-properties. */ -export type DeepPartial = T extends object - ? { - [P in keyof T]?: DeepPartial - } +export type DeepPartial = T extends Array + ? DeepPartial[] + : T extends Map + ? Map, DeepPartial> + : T extends Set + ? Set> + : T extends object + ? { [K in keyof T]?: DeepPartial } : T diff --git a/test/github-issues/8681/entity/item.entity.ts b/test/github-issues/8681/entity/item.entity.ts new file mode 100644 index 0000000000..0ba6819f72 --- /dev/null +++ b/test/github-issues/8681/entity/item.entity.ts @@ -0,0 +1,11 @@ +import { Entity, ManyToOne, PrimaryGeneratedColumn } from "../../../../src" +import { Thing } from "./thing.entity" + +@Entity() +export class Item { + @PrimaryGeneratedColumn() + id!: number + + @ManyToOne(() => Thing, (thing) => thing.items) + thing!: Thing +} diff --git a/test/github-issues/8681/entity/thing.entity.ts b/test/github-issues/8681/entity/thing.entity.ts new file mode 100644 index 0000000000..8c7e8c0d59 --- /dev/null +++ b/test/github-issues/8681/entity/thing.entity.ts @@ -0,0 +1,11 @@ +import { Entity, OneToMany, PrimaryGeneratedColumn } from "../../../../src" +import { Item } from "./item.entity" + +@Entity() +export class Thing { + @PrimaryGeneratedColumn() + id!: number + + @OneToMany(() => Item, (item) => item.thing) + items!: Item[] +} diff --git a/test/github-issues/8681/issue-8681.ts b/test/github-issues/8681/issue-8681.ts new file mode 100644 index 0000000000..eafb91537d --- /dev/null +++ b/test/github-issues/8681/issue-8681.ts @@ -0,0 +1,45 @@ +import "../../utils/test-setup" +import { + closeTestingConnections, + createTestingConnections, + reloadTestingDatabases, +} from "../../utils/test-utils" +import { DataSource, DeepPartial } from "../../../src" +import { expect } from "chai" +import { Thing } from "./entity/thing.entity" +import { Item } from "./entity/item.entity" + +describe("github issues > #8681 DeepPartial simplification breaks the .create() and .save() method in certain cases.", () => { + let connections: DataSource[] + before( + async () => + (connections = await createTestingConnections({ + entities: [__dirname + "/entity/*{.js,.ts}"], + schemaCreate: true, + dropSchema: true, + })), + ) + beforeEach(() => reloadTestingDatabases(connections)) + after(() => closeTestingConnections(connections)) + + it("should .save() and .create() complex deep partial entities", () => + Promise.all( + connections.map(async (connection) => { + const myThing: DeepPartial = { + items: [{ id: 1 }, { id: 2 }], + } + + const thing = connection.manager.create(Thing, myThing) + await connection.getRepository(Thing).save(myThing) + + const items = connection.manager.create(Item, myThing.items) + if (myThing.items) + await connection.getRepository(Item).save(myThing.items) + + const dbItems = await connection.manager.find(Item) + expect(dbItems).to.have.length(2) + + return { thing, items } + }), + )) +})