Skip to content

Commit b3e5364

Browse files
authored
feat: Add support for primitives and undefined values
* test: add more test scenarios * feat: add support to more types * restore: restore last version
1 parent 984ca21 commit b3e5364

File tree

7 files changed

+84
-14
lines changed

7 files changed

+84
-14
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
node_modules/
2-
dist/
2+
dist/
3+
.idea/

src/Primitives.ts

+16-12
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,20 @@ type MethodsAndProperties<T> = { [key in keyof T]: T[key] };
77

88
type Properties<T> = Omit<MethodsAndProperties<T>, Methods<T>>;
99

10-
type ValueObjectValue<T> = {
11-
[key in keyof T]: T[key] extends { value: unknown }
12-
? Pick<T[key], "value">["value"]
13-
: T[key] extends Array<{ value: unknown }>
14-
? Pick<T[key][number], "value">["value"][]
15-
: T[key] extends Array<Object>
16-
? Primitives<T[key][number]>[]
17-
: T[key] extends Object
18-
? Primitives<T[key]>
19-
: T[key];
20-
};
10+
type PrimitiveTypes = string | number | boolean | Date | undefined | null;
11+
12+
type ValueObjectValue<T> = T extends PrimitiveTypes
13+
? T
14+
: T extends { value: infer U }
15+
? U
16+
: T extends Array<{ value: infer U }>
17+
? U[]
18+
: T extends Array<infer U>
19+
? Array<ValueObjectValue<U>>
20+
: T extends { [K in keyof Properties<T>]: infer U }
21+
? { [K in keyof Properties<T>]: ValueObjectValue<U> }
22+
: never;
2123

22-
export type Primitives<T> = ValueObjectValue<Properties<T>>;
24+
export type Primitives<T> = {
25+
[key in keyof Properties<T>]: ValueObjectValue<T[key]>;
26+
};

tests/Primitives.test.ts

+26-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { expectTypeOf } from "expect-type";
22

3-
import { Primitives } from "../src/Primitives";
3+
import { Primitives } from "../src";
44
import { Course } from "./Course";
55
import { DeliveryInfo } from "./DeliveryInfo";
66
import { Learner } from "./Learner";
7+
import { Product } from "./Product";
78
import { User } from "./User";
9+
import { Video } from "./Video";
810

911
describe("Primitives", () => {
1012
it("should ensure to only return primitive properties excluding methods", () => {
@@ -52,4 +54,27 @@ describe("Primitives", () => {
5254

5355
expectTypeOf<actualPrimitives>().toEqualTypeOf<expectedPrimitives>();
5456
});
57+
58+
it("should get primitive type in case it is not a value object", () => {
59+
type actualPrimitives = Primitives<Product>;
60+
61+
type expectedPrimitives = {
62+
readonly active: boolean;
63+
readonly createdAt: Date;
64+
};
65+
66+
expectTypeOf<actualPrimitives>().toEqualTypeOf<expectedPrimitives>();
67+
});
68+
69+
it("should infer the optional properties", () => {
70+
type actualPrimitives = Primitives<Video>;
71+
72+
type expectedPrimitives = {
73+
readonly id: string;
74+
readonly name: string | undefined;
75+
readonly duration: number | undefined;
76+
};
77+
78+
expectTypeOf<actualPrimitives>().toEqualTypeOf<expectedPrimitives>();
79+
});
5580
});

tests/Product.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Primitives } from "../src";
2+
3+
export class Product {
4+
constructor(
5+
public readonly active: boolean,
6+
public readonly createdAt: Date
7+
) {}
8+
9+
toPrimitives(): Primitives<Product> {
10+
return {
11+
active: this.active,
12+
createdAt: this.createdAt,
13+
};
14+
}
15+
}

tests/Video.ts

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Primitives } from "../src";
2+
import { VideoId } from "./VideoId";
3+
import { VideoName } from "./VideoName";
4+
5+
export class Video {
6+
public constructor(
7+
public readonly id: VideoId,
8+
public readonly name: VideoName | undefined,
9+
public readonly duration: number | undefined
10+
) {}
11+
12+
public toPrimitives(): Primitives<Video> {
13+
return {
14+
id: this.id.value,
15+
name: this.name?.value,
16+
duration: this.duration,
17+
};
18+
}
19+
}

tests/VideoId.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { StringValueObject } from "./StringValueObject";
2+
3+
export class VideoId extends StringValueObject {}

tests/VideoName.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { StringValueObject } from "./StringValueObject";
2+
3+
export class VideoName extends StringValueObject {}

0 commit comments

Comments
 (0)