Skip to content

Commit b965b0b

Browse files
authored
Merge pull request #5 from Atrocit/1-circular-types-ts-59
Add tests to confirm circular types are ok even if recursing deeply
2 parents 1e0d1a6 + 66aa5df commit b965b0b

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

tests/types/circularTypes.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { describe, expectTypeOf, it } from "vitest";
2+
import { defineEntity, defineField, defineIdField, Farstorm, OutputType } from "../../src/main";
3+
4+
describe('Types: circular references', () => {
5+
const entityDefinitions = {
6+
'EntityA': defineEntity({
7+
fields: {
8+
id: defineIdField(),
9+
name: defineField('string', false),
10+
a1: defineField('string', false),
11+
a2: defineField('string', false),
12+
a3: defineField('string', false),
13+
a4: defineField('string', false),
14+
a5: defineField('string', false),
15+
a6: defineField('string', false),
16+
a7: defineField('string', false),
17+
a8: defineField('string', false),
18+
a9: defineField('string', false),
19+
a10: defineField('string', false),
20+
a11: defineField('string', false),
21+
a12: defineField('string', false),
22+
a13: defineField('string', false),
23+
a14: defineField('string', false),
24+
a15: defineField('string', false),
25+
a16: defineField('string', false),
26+
a17: defineField('string', false),
27+
a18: defineField('string', false),
28+
a19: defineField('string', false),
29+
},
30+
oneToMany: {
31+
b: { entity: 'EntityB', inverse: 'a' },
32+
bOther: { entity: 'EntityB', inverse: 'anotherA' },
33+
},
34+
}),
35+
'EntityB': defineEntity({
36+
fields: {
37+
id: defineIdField(),
38+
name: defineField('string', false),
39+
b1: defineField('string', false),
40+
b2: defineField('string', false),
41+
b3: defineField('string', false),
42+
b4: defineField('string', false),
43+
b5: defineField('string', false),
44+
b6: defineField('string', false),
45+
b7: defineField('string', false),
46+
b8: defineField('string', false),
47+
b9: defineField('string', false),
48+
b10: defineField('string', false),
49+
b11: defineField('string', false),
50+
b12: defineField('string', false),
51+
b13: defineField('string', false),
52+
b14: defineField('string', false),
53+
b15: defineField('string', false),
54+
b16: defineField('string', false),
55+
b17: defineField('string', false),
56+
b18: defineField('string', false),
57+
b19: defineField('string', false),
58+
},
59+
manyToOne: {
60+
a: { entity: 'EntityA', nullable: false },
61+
anotherA: { entity: 'EntityA', nullable: true },
62+
},
63+
}),
64+
};
65+
66+
it('should still keep types even if recursing deeply', async () => {
67+
type OrmOutput<N extends keyof typeof entityDefinitions> = OutputType<typeof entityDefinitions, typeof entityDefinitions[N]>;
68+
69+
type BaseA = OrmOutput<'EntityA'>;
70+
type BaseB = OrmOutput<'EntityB'>;
71+
72+
type AtoB1 = Awaited<BaseA['b']>[number];
73+
type BtoA1 = Awaited<BaseB['a']>;
74+
75+
expectTypeOf<AtoB1>().toEqualTypeOf<BaseB>();
76+
expectTypeOf<BtoA1>().toEqualTypeOf<BaseA>();
77+
78+
type AtoBOther = Awaited<BaseA['bOther']>[number];
79+
type BtoAOther = NonNullable<Awaited<BaseB['anotherA']>>;
80+
81+
expectTypeOf<AtoBOther>().toEqualTypeOf<BaseB>();
82+
expectTypeOf<BtoAOther>().toEqualTypeOf<BaseA>();
83+
84+
type GetB<T extends BaseA> = Awaited<T['b']>[number];
85+
type GetA<T extends BaseB> = Awaited<T['a']>;
86+
type DeepChainAtoB = GetB<GetA<GetB<GetA<GetB<GetA<GetB<GetA<GetB<GetA<GetB<GetA<GetB<GetA<GetB<GetA<GetB<BaseA>>>>>>>>>>>>>>>>>;
87+
expectTypeOf<DeepChainAtoB>().toEqualTypeOf<BaseB>();
88+
});
89+
});

0 commit comments

Comments
 (0)