Skip to main content

Emi object data type

Example schema:

name: MyObjectClass
fields:
- name: profile
type: object
fields:
- name: firstName
type: string
- name: age
type: int

  • object lets you embed nested fields inside your class.
  • Works like inline type definition in TypeScript.
  • Defaults to an empty object {} if not specified.
  • object? allows null/ undefined.
import { withPrefix } from "./sdk/common/withPrefix";
/**
* The base class definition for myObjectClassDto
**/
export class MyObjectClassDto {
/**
*
* @type {MyObjectClassDto.Profile}
**/
#profile!: InstanceType<typeof MyObjectClassDto.Profile>;
/**
*
* @returns {MyObjectClassDto.Profile}
**/
get profile() {
return this.#profile;
}
/**
*
* @type {MyObjectClassDto.Profile}
**/
set profile(value: InstanceType<typeof MyObjectClassDto.Profile>) {
// For objects, the sub type needs to always be instance of the sub class.
if (value instanceof MyObjectClassDto.Profile) {
this.#profile = value;
} else {
this.#profile = new MyObjectClassDto.Profile(value);
}
}
setProfile(value: InstanceType<typeof MyObjectClassDto.Profile>) {
this.profile = value;
return this;
}
/**
* The base class definition for profile
**/
static Profile = class Profile {
/**
*
* @type {string}
**/
#firstName: string = "";
/**
*
* @returns {string}
**/
get firstName() {
return this.#firstName;
}
/**
*
* @type {string}
**/
set firstName(value: string) {
this.#firstName = String(value);
}
setFirstName(value: string) {
this.firstName = value;
return this;
}
/**
*
* @type {number}
**/
#age: number = 0;
/**
*
* @returns {number}
**/
get age() {
return this.#age;
}
/**
*
* @type {number}
**/
set age(value: number) {
const correctType = typeof value === "number";
const parsedValue = correctType ? value : Number(value);
if (!Number.isNaN(parsedValue)) {
this.#age = parsedValue;
}
}
setAge(value: number) {
this.age = value;
return this;
}
constructor(data: unknown = undefined) {
if (data === null || data === undefined) {
return;
}
if (typeof data === "string") {
this.applyFromObject(JSON.parse(data));
} else if (this.#isJsonAppliable(data)) {
this.applyFromObject(data);
} else {
throw new Error(
"Instance cannot be created on an unknown value, check the content being passed. got: " +
typeof data,
);
}
}
#isJsonAppliable(obj: unknown) {
const g = globalThis as unknown as { Buffer: any; Blob: any };
const isBuffer =
typeof g.Buffer !== "undefined" &&
typeof g.Buffer.isBuffer === "function" &&
g.Buffer.isBuffer(obj);
const isBlob = typeof g.Blob !== "undefined" && obj instanceof g.Blob;
return (
obj &&
typeof obj === "object" &&
!Array.isArray(obj) &&
!isBuffer &&
!(obj instanceof ArrayBuffer) &&
!isBlob
);
}
/**
* casts the fields of a javascript object into the class properties one by one
**/
applyFromObject(data = {}) {
const d = data as Partial<Profile>;
if (d.firstName !== undefined) {
this.firstName = d.firstName;
}
if (d.age !== undefined) {
this.age = d.age;
}
}
/**
* Special toJSON override, since the field are private,
* Json stringify won't see them unless we mention it explicitly.
**/
toJSON() {
return {
firstName: this.#firstName,
age: this.#age,
};
}
toString() {
return JSON.stringify(this);
}
static get Fields() {
return {
firstName: "firstName",
age: "age",
};
}
/**
* Creates an instance of MyObjectClassDto.Profile, and possibleDtoObject
* needs to satisfy the type requirement fully, otherwise typescript compile would
* be complaining.
**/
static from(possibleDtoObject: MyObjectClassDtoType.ProfileType) {
return new MyObjectClassDto.Profile(possibleDtoObject);
}
/**
* Creates an instance of MyObjectClassDto.Profile, and partialDtoObject
* needs to satisfy the type, but partially, and rest of the content would
* be constructed according to data types and nullability.
**/
static with(
partialDtoObject: PartialDeep<MyObjectClassDtoType.ProfileType>,
) {
return new MyObjectClassDto.Profile(partialDtoObject);
}
copyWith(
partial: PartialDeep<MyObjectClassDtoType.ProfileType>,
): InstanceType<typeof MyObjectClassDto.Profile> {
return new MyObjectClassDto.Profile({ ...this.toJSON(), ...partial });
}
clone(): InstanceType<typeof MyObjectClassDto.Profile> {
return new MyObjectClassDto.Profile(this.toJSON());
}
};
constructor(data: unknown = undefined) {
if (data === null || data === undefined) {
this.#lateInitFields();
return;
}
if (typeof data === "string") {
this.applyFromObject(JSON.parse(data));
} else if (this.#isJsonAppliable(data)) {
this.applyFromObject(data);
} else {
throw new Error(
"Instance cannot be created on an unknown value, check the content being passed. got: " +
typeof data,
);
}
}
#isJsonAppliable(obj: unknown) {
const g = globalThis as unknown as { Buffer: any; Blob: any };
const isBuffer =
typeof g.Buffer !== "undefined" &&
typeof g.Buffer.isBuffer === "function" &&
g.Buffer.isBuffer(obj);
const isBlob = typeof g.Blob !== "undefined" && obj instanceof g.Blob;
return (
obj &&
typeof obj === "object" &&
!Array.isArray(obj) &&
!isBuffer &&
!(obj instanceof ArrayBuffer) &&
!isBlob
);
}
/**
* casts the fields of a javascript object into the class properties one by one
**/
applyFromObject(data = {}) {
const d = data as Partial<MyObjectClassDto>;
if (d.profile !== undefined) {
this.profile = d.profile;
}
this.#lateInitFields(data);
}
/**
* These are the class instances, which need to be initialised, regardless of the constructor incoming data
**/
#lateInitFields(data = {}) {
const d = data as Partial<MyObjectClassDto>;
if (!(d.profile instanceof MyObjectClassDto.Profile)) {
this.profile = new MyObjectClassDto.Profile(d.profile || {});
}
}
/**
* Special toJSON override, since the field are private,
* Json stringify won't see them unless we mention it explicitly.
**/
toJSON() {
return {
profile: this.#profile,
};
}
toString() {
return JSON.stringify(this);
}
static get Fields() {
return {
profile$: "profile",
get profile() {
return withPrefix("profile", MyObjectClassDto.Profile.Fields);
},
};
}
/**
* Creates an instance of MyObjectClassDto, and possibleDtoObject
* needs to satisfy the type requirement fully, otherwise typescript compile would
* be complaining.
**/
static from(possibleDtoObject: MyObjectClassDtoType) {
return new MyObjectClassDto(possibleDtoObject);
}
/**
* Creates an instance of MyObjectClassDto, and partialDtoObject
* needs to satisfy the type, but partially, and rest of the content would
* be constructed according to data types and nullability.
**/
static with(partialDtoObject: PartialDeep<MyObjectClassDtoType>) {
return new MyObjectClassDto(partialDtoObject);
}
copyWith(
partial: PartialDeep<MyObjectClassDtoType>,
): InstanceType<typeof MyObjectClassDto> {
return new MyObjectClassDto({ ...this.toJSON(), ...partial });
}
clone(): InstanceType<typeof MyObjectClassDto> {
return new MyObjectClassDto(this.toJSON());
}
}
export abstract class MyObjectClassDtoFactory {
abstract create(data: unknown): MyObjectClassDto;
}
type PartialDeep<T> = {
[P in keyof T]?: T[P] extends Array<infer U>
? Array<PartialDeep<U>>
: T[P] extends object
? PartialDeep<T[P]>
: T[P];
};
/**
* The base type definition for myObjectClassDto
**/
export type MyObjectClassDtoType = {
/**
*
* @type {MyObjectClassDtoType.ProfileType}
**/
profile: MyObjectClassDtoType.ProfileType;
};
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace MyObjectClassDtoType {
/**
* The base type definition for profileType
**/
export type ProfileType = {
/**
*
* @type {string}
**/
firstName: string;
/**
*
* @type {number}
**/
age: number;
};
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace ProfileType {}
}

Nullable version:

name: MyObjectClass
fields:
- name: optionalProfile
type: object?
fields:
- name: lastName
type: string

Defaults to undefined, but you can assign an object with required child fields or null.

import { withPrefix } from "./sdk/common/withPrefix";
/**
* The base class definition for myObjectClassDto
**/
export class MyObjectClassDto {
/**
*
* @type {MyObjectClassDto.OptionalProfile}
**/
#optionalProfile?:
| InstanceType<typeof MyObjectClassDto.OptionalProfile>
| null
| undefined
| null = undefined;
/**
*
* @returns {MyObjectClassDto.OptionalProfile}
**/
get optionalProfile() {
return this.#optionalProfile;
}
/**
*
* @type {MyObjectClassDto.OptionalProfile}
**/
set optionalProfile(
value:
| InstanceType<typeof MyObjectClassDto.OptionalProfile>
| null
| undefined
| null
| undefined,
) {
// For objects, the sub type needs to always be instance of the sub class.
if (value instanceof MyObjectClassDto.OptionalProfile) {
this.#optionalProfile = value;
} else {
this.#optionalProfile = new MyObjectClassDto.OptionalProfile(value);
}
}
setOptionalProfile(
value:
| InstanceType<typeof MyObjectClassDto.OptionalProfile>
| null
| undefined
| null
| undefined,
) {
this.optionalProfile = value;
return this;
}
/**
* The base class definition for optionalProfile
**/
static OptionalProfile = class OptionalProfile {
/**
*
* @type {string}
**/
#lastName: string = "";
/**
*
* @returns {string}
**/
get lastName() {
return this.#lastName;
}
/**
*
* @type {string}
**/
set lastName(value: string) {
this.#lastName = String(value);
}
setLastName(value: string) {
this.lastName = value;
return this;
}
constructor(data: unknown = undefined) {
if (data === null || data === undefined) {
return;
}
if (typeof data === "string") {
this.applyFromObject(JSON.parse(data));
} else if (this.#isJsonAppliable(data)) {
this.applyFromObject(data);
} else {
throw new Error(
"Instance cannot be created on an unknown value, check the content being passed. got: " +
typeof data,
);
}
}
#isJsonAppliable(obj: unknown) {
const g = globalThis as unknown as { Buffer: any; Blob: any };
const isBuffer =
typeof g.Buffer !== "undefined" &&
typeof g.Buffer.isBuffer === "function" &&
g.Buffer.isBuffer(obj);
const isBlob = typeof g.Blob !== "undefined" && obj instanceof g.Blob;
return (
obj &&
typeof obj === "object" &&
!Array.isArray(obj) &&
!isBuffer &&
!(obj instanceof ArrayBuffer) &&
!isBlob
);
}
/**
* casts the fields of a javascript object into the class properties one by one
**/
applyFromObject(data = {}) {
const d = data as Partial<OptionalProfile>;
if (d.lastName !== undefined) {
this.lastName = d.lastName;
}
}
/**
* Special toJSON override, since the field are private,
* Json stringify won't see them unless we mention it explicitly.
**/
toJSON() {
return {
lastName: this.#lastName,
};
}
toString() {
return JSON.stringify(this);
}
static get Fields() {
return {
lastName: "lastName",
};
}
/**
* Creates an instance of MyObjectClassDto.OptionalProfile, and possibleDtoObject
* needs to satisfy the type requirement fully, otherwise typescript compile would
* be complaining.
**/
static from(possibleDtoObject: MyObjectClassDtoType.OptionalProfileType) {
return new MyObjectClassDto.OptionalProfile(possibleDtoObject);
}
/**
* Creates an instance of MyObjectClassDto.OptionalProfile, and partialDtoObject
* needs to satisfy the type, but partially, and rest of the content would
* be constructed according to data types and nullability.
**/
static with(
partialDtoObject: PartialDeep<MyObjectClassDtoType.OptionalProfileType>,
) {
return new MyObjectClassDto.OptionalProfile(partialDtoObject);
}
copyWith(
partial: PartialDeep<MyObjectClassDtoType.OptionalProfileType>,
): InstanceType<typeof MyObjectClassDto.OptionalProfile> {
return new MyObjectClassDto.OptionalProfile({
...this.toJSON(),
...partial,
});
}
clone(): InstanceType<typeof MyObjectClassDto.OptionalProfile> {
return new MyObjectClassDto.OptionalProfile(this.toJSON());
}
};
constructor(data: unknown = undefined) {
if (data === null || data === undefined) {
return;
}
if (typeof data === "string") {
this.applyFromObject(JSON.parse(data));
} else if (this.#isJsonAppliable(data)) {
this.applyFromObject(data);
} else {
throw new Error(
"Instance cannot be created on an unknown value, check the content being passed. got: " +
typeof data,
);
}
}
#isJsonAppliable(obj: unknown) {
const g = globalThis as unknown as { Buffer: any; Blob: any };
const isBuffer =
typeof g.Buffer !== "undefined" &&
typeof g.Buffer.isBuffer === "function" &&
g.Buffer.isBuffer(obj);
const isBlob = typeof g.Blob !== "undefined" && obj instanceof g.Blob;
return (
obj &&
typeof obj === "object" &&
!Array.isArray(obj) &&
!isBuffer &&
!(obj instanceof ArrayBuffer) &&
!isBlob
);
}
/**
* casts the fields of a javascript object into the class properties one by one
**/
applyFromObject(data = {}) {
const d = data as Partial<MyObjectClassDto>;
if (d.optionalProfile !== undefined) {
this.optionalProfile = d.optionalProfile;
}
}
/**
* Special toJSON override, since the field are private,
* Json stringify won't see them unless we mention it explicitly.
**/
toJSON() {
return {
optionalProfile: this.#optionalProfile,
};
}
toString() {
return JSON.stringify(this);
}
static get Fields() {
return {
optionalProfile$: "optionalProfile",
get optionalProfile() {
return withPrefix(
"optionalProfile",
MyObjectClassDto.OptionalProfile.Fields,
);
},
};
}
/**
* Creates an instance of MyObjectClassDto, and possibleDtoObject
* needs to satisfy the type requirement fully, otherwise typescript compile would
* be complaining.
**/
static from(possibleDtoObject: MyObjectClassDtoType) {
return new MyObjectClassDto(possibleDtoObject);
}
/**
* Creates an instance of MyObjectClassDto, and partialDtoObject
* needs to satisfy the type, but partially, and rest of the content would
* be constructed according to data types and nullability.
**/
static with(partialDtoObject: PartialDeep<MyObjectClassDtoType>) {
return new MyObjectClassDto(partialDtoObject);
}
copyWith(
partial: PartialDeep<MyObjectClassDtoType>,
): InstanceType<typeof MyObjectClassDto> {
return new MyObjectClassDto({ ...this.toJSON(), ...partial });
}
clone(): InstanceType<typeof MyObjectClassDto> {
return new MyObjectClassDto(this.toJSON());
}
}
export abstract class MyObjectClassDtoFactory {
abstract create(data: unknown): MyObjectClassDto;
}
type PartialDeep<T> = {
[P in keyof T]?: T[P] extends Array<infer U>
? Array<PartialDeep<U>>
: T[P] extends object
? PartialDeep<T[P]>
: T[P];
};
/**
* The base type definition for myObjectClassDto
**/
export type MyObjectClassDtoType = {
/**
*
* @type {MyObjectClassDtoType.OptionalProfileType}
**/
optionalProfile?: MyObjectClassDtoType.OptionalProfileType;
};
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace MyObjectClassDtoType {
/**
* The base type definition for optionalProfileType
**/
export type OptionalProfileType = {
/**
*
* @type {string}
**/
lastName: string;
};
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace OptionalProfileType {}
}