Skip to content

Commit

Permalink
fix(core): improve EntitySchema typing for repository option
Browse files Browse the repository at this point in the history
Closes #5006
  • Loading branch information
B4nan committed Dec 12, 2023
1 parent bf34ab7 commit 37ee42e
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 8 deletions.
27 changes: 20 additions & 7 deletions packages/core/src/typings.ts
Expand Up @@ -72,11 +72,18 @@ type PrimaryPropToType<T, Keys extends (keyof T)[]> = {
};

type ReadonlyPrimary<T> = T extends any[] ? Readonly<T> : T;
export type Primary<T> = T extends { [PrimaryKeyProp]?: infer PK }
? (PK extends keyof T ? ReadonlyPrimary<UnwrapPrimary<T[PK]>> : (PK extends (keyof T)[] ? ReadonlyPrimary<PrimaryPropToType<T, PK>> : PK)) : T extends { _id?: infer PK }
? ReadonlyPrimary<PK> | string : T extends { uuid?: infer PK }
? ReadonlyPrimary<PK> : T extends { id?: infer PK }
? ReadonlyPrimary<PK> : T;
export type Primary<T> =
IsAny<T> extends true
? any
: T extends { [PrimaryKeyProp]?: infer PK }
? (PK extends keyof T ? ReadonlyPrimary<UnwrapPrimary<T[PK]>> : (PK extends (keyof T)[] ? ReadonlyPrimary<PrimaryPropToType<T, PK>> : PK))
: T extends { _id?: infer PK }
? ReadonlyPrimary<PK> | string
: T extends { uuid?: infer PK }
? ReadonlyPrimary<PK>
: T extends { id?: infer PK }
? ReadonlyPrimary<PK>
: T;
export type PrimaryProperty<T> = T extends { [PrimaryKeyProp]?: infer PK }
? (PK extends keyof T ? PK : (PK extends any[] ? PK[number] : never)) : T extends { _id?: any }
? (T extends { id?: any } ? 'id' | '_id' : '_id') : T extends { uuid?: any }
Expand Down Expand Up @@ -292,13 +299,19 @@ export type ScalarRef<T> = ScalarReference<T>;
/** Alias for `Reference<T> & { id: number }` (see {@apilink Ref}). */
export type EntityRef<T> = true extends IsUnknown<PrimaryProperty<T>>
? Reference<T>
: ({ [K in PrimaryProperty<T> & keyof T]: T[K] } & Reference<T>);
: IsAny<T> extends true
? Reference<T>
: ({ [K in PrimaryProperty<T> & keyof T]: T[K] } & Reference<T>);

/**
* Ref type represents a `Reference` instance, and adds the primary keys to its prototype automatically, so you can do
* `ref.id` instead of `ref.unwrap().id`. It resolves to either `ScalarRef` or `EntityRef`, based on the type argument.
*/
export type Ref<T> = T extends Scalar ? ScalarReference<T> : EntityRef<T>;
export type Ref<T> = IsAny<T> extends true
? Reference<T>
: T extends Scalar
? ScalarReference<T>
: EntityRef<T>;

type EntityDTONested<T> = T extends undefined | null ? T : EntityDTO<T>;
export type EntityDTOProp<T> = T extends Scalar
Expand Down
22 changes: 21 additions & 1 deletion tests/types.test.ts
@@ -1,4 +1,4 @@
import { EntityRepository, OptionalProps, ref, wrap } from '@mikro-orm/core';
import { Constructor, EntityRepository, EntitySchema, OptionalProps, ref, wrap } from '@mikro-orm/core';
import type { BaseEntity, Ref, Reference, Collection, EntityManager, EntityName, RequiredEntityData } from '@mikro-orm/core';
import type { Has, IsExact } from 'conditional-type-checks';
import { assert } from 'conditional-type-checks';
Expand Down Expand Up @@ -822,4 +822,24 @@ describe('check typings', () => {
}
});

test('GH #5006', async () => {
interface User {
id: number;
name: string;
}

interface UserRepository extends EntityRepository<User> {
test(): number;
}

const schema = new EntitySchema<User>({
name: 'User',
repository: () => ({} as Constructor<UserRepository>),
properties: {
id: { type: 'number', primary: true },
name: { type: 'string' },
},
});
});

});

0 comments on commit 37ee42e

Please sign in to comment.