Add runtime type checking and errors when invalid values are provided.

This commit is contained in:
Madeorsk 2025-03-30 11:33:22 +02:00
parent f5502109ac
commit 8afce56b9e
Signed by: Madeorsk
GPG key ID: 677E51CA765BB79F
22 changed files with 273 additions and 10 deletions

4
src/errors/index.ts Normal file
View file

@ -0,0 +1,4 @@
export * from "./sharkitek-error";
export * from "./type-error";
export * from "./invalid-type-value-error";

View file

@ -0,0 +1,13 @@
import {TypeError} from "./type-error";
import {Type} from "../model/types/type";
/**
* A Sharkitek type error when the passed value is invalid.
*/
export class InvalidTypeValueError<SerializedType, ModelType> extends TypeError<SerializedType, ModelType>
{
constructor(public type: Type<SerializedType, ModelType>, public value: any, message?: string)
{
super(type, message ?? `${JSON.stringify(value)} is an invalid value`)
}
}

View file

@ -0,0 +1,6 @@
/**
* A Sharkitek error.
*/
export class SharkitekError extends Error
{
}

13
src/errors/type-error.ts Normal file
View file

@ -0,0 +1,13 @@
import {SharkitekError} from "./sharkitek-error";
import {Type} from "../model/types/type";
/**
* A Sharkitek type error.
*/
export class TypeError<SerializedType, ModelType> extends SharkitekError
{
constructor(public type: Type<SerializedType, ModelType>, message?: string)
{
super(`Error in type ${type.constructor.name}${message ? `: ${message}` : ""}`);
}
}

View file

@ -1,4 +1,5 @@
import * as s from "./model";
export * from "./model";
export * from "./errors";
export { s };
export default s;

View file

@ -1,5 +1,5 @@
import * as property from "./properties";
export { property };
export {property};
export * from "./model";
export {Definition} from "./property-definition";

View file

@ -1,5 +1,6 @@
import {Type} from "./type";
import {define, Definition} from "../property-definition";
import {InvalidTypeValueError} from "../../errors";
/**
* Type of an array of values.
@ -20,6 +21,8 @@ export class ArrayType<SerializedValueType, SharkitekValueType> extends Type<Ser
if (value === undefined) return undefined;
if (value === null) return null;
if (!Array.isArray(value)) throw new InvalidTypeValueError(this, value, "value must be an array");
return value.map((value) => (
// Serializing each value of the array.
this.valueDefinition.type.serialize(value)
@ -31,6 +34,8 @@ export class ArrayType<SerializedValueType, SharkitekValueType> extends Type<Ser
if (value === undefined) return undefined;
if (value === null) return null;
if (!Array.isArray(value)) throw new InvalidTypeValueError(this, value, "value must be an array");
return value.map((serializedValue) => (
// Deserializing each value of the array.
this.valueDefinition.type.deserialize(serializedValue)
@ -42,6 +47,8 @@ export class ArrayType<SerializedValueType, SharkitekValueType> extends Type<Ser
if (value === undefined) return undefined;
if (value === null) return null;
if (!Array.isArray(value)) throw new InvalidTypeValueError(this, value, "value must be an array");
// Serializing diff of all elements.
return value.map((value) => this.valueDefinition.type.serializeDiff(value) as SerializedValueType);
}
@ -94,6 +101,8 @@ export class ArrayType<SerializedValueType, SharkitekValueType> extends Type<Ser
// Handle NULL / undefined array.
if (!array) return super.clone(array);
if (!Array.isArray(array)) throw new InvalidTypeValueError(this, array, "value must be an array");
// Initialize an empty array.
const cloned = [] as T;

View file

@ -1,5 +1,6 @@
import {Type} from "./type";
import {define, Definition} from "../property-definition";
import {InvalidTypeValueError} from "../../errors";
/**
* Type of dates.
@ -18,6 +19,7 @@ export class DateType extends Type<string, Date>
{
if (value === undefined) return undefined;
if (value === null) return null;
if (!(value instanceof Date)) throw new InvalidTypeValueError(this, value, "value must be a date");
if (isNaN(value?.valueOf())) return value?.toString();
return value?.toISOString();

View file

@ -1,5 +1,6 @@
import {Type} from "./type";
import {define, Definition} from "../property-definition";
import {InvalidTypeValueError} from "../../errors";
/**
* Type of decimal numbers.
@ -18,6 +19,7 @@ export class DecimalType extends Type<string, number>
{
if (value === undefined) return undefined;
if (value === null) return null;
if (typeof value !== "number" && typeof value !== "string") throw new InvalidTypeValueError(this, value, "value must be a number");
return value?.toString();
}

View file

@ -8,6 +8,7 @@ import {
ModelShape,
SerializedModel
} from "../model";
import {InvalidTypeValueError} from "../../errors";
/**
* Type of a Sharkitek model value.
@ -36,6 +37,9 @@ export class ModelType<T extends object, Shape extends ModelShape<T>, Identifier
if (value === undefined) return undefined;
if (value === null) return null;
if (!(value instanceof this.definedModel.definition.Class))
throw new InvalidTypeValueError(this, value, `value must be a compatible model (given ${value.constructor.name}, expected ${this.definedModel.definition.Class.name})`);
// Serializing the given model.
return this.definedModel.model(value).serialize();
}
@ -45,6 +49,9 @@ export class ModelType<T extends object, Shape extends ModelShape<T>, Identifier
if (value === undefined) return undefined;
if (value === null) return null;
if (typeof value !== "object" || Array.isArray(value))
throw new InvalidTypeValueError(this, value, "value must be an object");
// Parse the given object in the new model.
return this.definedModel.parse(value);
}
@ -54,12 +61,21 @@ export class ModelType<T extends object, Shape extends ModelShape<T>, Identifier
if (value === undefined) return undefined;
if (value === null) return null;
if (!(value instanceof this.definedModel.definition.Class))
throw new InvalidTypeValueError(this, value, `value must be a compatible model (given ${value.constructor.name}, expected ${this.definedModel.definition.Class.name})`);
// Serializing the given model.
return this.definedModel.model(value).serializeDiff();
}
resetDiff(value: ModelInstance<T, Shape, Identifier>|null|undefined): void
{
if (value === undefined) return;
if (value === null) return;
if (!(value instanceof this.definedModel.definition.Class))
throw new InvalidTypeValueError(this, value, `value must be a compatible model (given ${value.constructor.name}, expected ${this.definedModel.definition.Class.name})`);
// Reset diff of the given model.
this.definedModel.model(value).resetDiff();
}
@ -71,6 +87,11 @@ export class ModelType<T extends object, Shape extends ModelShape<T>, Identifier
if (currentValue === undefined) return true; // Original value is not undefined.
if (currentValue === null) return true; // Original value is not null.
if (!(originalValue instanceof this.definedModel.definition.Class))
throw new InvalidTypeValueError(this, originalValue, `value must be a compatible model (given ${originalValue.constructor.name}, expected ${this.definedModel.definition.Class.name})`);
if (!(currentValue instanceof this.definedModel.definition.Class))
throw new InvalidTypeValueError(this, currentValue, `value must be a compatible model (given ${currentValue.constructor.name}, expected ${this.definedModel.definition.Class.name})`);
// If the current value is dirty, it has changed.
return this.definedModel.model(currentValue).isDirty();
}
@ -82,6 +103,11 @@ export class ModelType<T extends object, Shape extends ModelShape<T>, Identifier
if (currentValue === undefined) return true; // Original value is not undefined.
if (currentValue === null) return true; // Original value is not null.
if (typeof originalValue !== "object" || Array.isArray(originalValue))
throw new InvalidTypeValueError(this, originalValue, "value must be an object");
if (typeof currentValue !== "object" || Array.isArray(currentValue))
throw new InvalidTypeValueError(this, currentValue, "value must be an object");
// If any property has changed, the value has changed.
for (const property of this.definedModel.properties)
if (property.definition.type.serializedHasChanged(originalValue?.[property.name], currentValue?.[property.name]))
@ -95,6 +121,9 @@ export class ModelType<T extends object, Shape extends ModelShape<T>, Identifier
// Handle NULL / undefined values.
if (!value) return super.clone(value);
if (!(value instanceof this.definedModel.definition.Class))
throw new InvalidTypeValueError(this, value, `value must be a compatible model (given ${value.constructor.name}, expected ${this.definedModel.definition.Class.name})`);
return this.definedModel.model(value).clone() as Type;
}
}

View file

@ -1,5 +1,6 @@
import {Type} from "./type";
import {define, Definition} from "../property-definition";
import {InvalidTypeValueError} from "../../errors";
/**
* Type of any numeric value.
@ -8,11 +9,21 @@ export class NumericType extends Type<number, number>
{
deserialize(value: number|null|undefined): number|null|undefined
{
if (value === undefined) return undefined;
if (value === null) return null;
if (typeof value !== "number") throw new InvalidTypeValueError(this, value, "value must be a number");
return value;
}
serialize(value: number|null|undefined): number|null|undefined
{
if (value === undefined) return undefined;
if (value === null) return null;
if (typeof value !== "number") throw new InvalidTypeValueError(this, value, "value must be a number");
return value;
}
}

View file

@ -1,6 +1,7 @@
import {Type} from "./type";
import {define, Definition} from "../property-definition";
import {ModelProperties, ModelPropertiesValues, ModelProperty, ModelShape, SerializedModel} from "../model";
import {InvalidTypeValueError} from "../../errors";
/**
* Type of a custom object.
@ -45,6 +46,9 @@ export class ObjectType<Shape extends ModelShape<T>, T extends object> extends T
if (value === undefined) return undefined;
if (value === null) return null;
if (typeof value !== "object" || Array.isArray(value))
throw new InvalidTypeValueError(this, value, "value must be an object");
// Initialize an empty object.
const obj: Partial<ModelPropertiesValues<T, Shape>> = {};
@ -61,6 +65,9 @@ export class ObjectType<Shape extends ModelShape<T>, T extends object> extends T
if (value === undefined) return undefined;
if (value === null) return null;
if (typeof value !== "object" || Array.isArray(value))
throw new InvalidTypeValueError(this, value, "value must be an object");
// Creating an empty serialized object.
const serializedObject: Partial<SerializedModel<T, Shape>> = {};
@ -80,6 +87,9 @@ export class ObjectType<Shape extends ModelShape<T>, T extends object> extends T
if (value === undefined) return undefined;
if (value === null) return null;
if (typeof value !== "object" || Array.isArray(value))
throw new InvalidTypeValueError(this, value, "value must be an object");
// Creating an empty serialized object.
const serializedObject: Partial<SerializedModel<T, Shape>> = {};
@ -96,6 +106,12 @@ export class ObjectType<Shape extends ModelShape<T>, T extends object> extends T
resetDiff(value: ModelPropertiesValues<T, Shape>|null|undefined)
{
if (value === undefined) return;
if (value === null) return;
if (typeof value !== "object" || Array.isArray(value))
throw new InvalidTypeValueError(this, value, "value must be an object");
// For each property, reset its diff.
for (const property of this.properties)
// keyof Shape is a subset of keyof T.
@ -109,6 +125,11 @@ export class ObjectType<Shape extends ModelShape<T>, T extends object> extends T
if (currentValue === undefined) return true; // Original value is not undefined.
if (currentValue === null) return true; // Original value is not null.
if (typeof originalValue !== "object" || Array.isArray(originalValue))
throw new InvalidTypeValueError(this, originalValue, "value must be an object");
if (typeof currentValue !== "object" || Array.isArray(currentValue))
throw new InvalidTypeValueError(this, currentValue, "value must be an object");
// If any property has changed, the value has changed.
for (const property of this.properties)
if (property.definition.type.hasChanged(originalValue?.[property.name as keyof T], currentValue?.[property.name as keyof T]))
@ -124,6 +145,11 @@ export class ObjectType<Shape extends ModelShape<T>, T extends object> extends T
if (currentValue === undefined) return true; // Original value is not undefined.
if (currentValue === null) return true; // Original value is not null.
if (typeof originalValue !== "object" || Array.isArray(originalValue))
throw new InvalidTypeValueError(this, originalValue, "value must be an object");
if (typeof currentValue !== "object" || Array.isArray(currentValue))
throw new InvalidTypeValueError(this, currentValue, "value must be an object");
// If any property has changed, the value has changed.
for (const property of this.properties)
if (property.definition.type.serializedHasChanged(originalValue?.[property.name], currentValue?.[property.name]))
@ -137,6 +163,9 @@ export class ObjectType<Shape extends ModelShape<T>, T extends object> extends T
// Handle NULL / undefined object.
if (!value) return super.clone(value);
if (typeof value !== "object" || Array.isArray(value))
throw new InvalidTypeValueError(this, value, "value must be an object");
// Initialize an empty object.
const cloned: Partial<ModelPropertiesValues<T, Shape>> = {};

View file

@ -8,12 +8,18 @@ export class StringType extends Type<string, string>
{
deserialize(value: string|null|undefined): string|null|undefined
{
return value;
if (value === undefined) return undefined;
if (value === null) return null;
return String(value);
}
serialize(value: string|null|undefined): string|null|undefined
{
return value;
if (value === undefined) return undefined;
if (value === null) return null;
return String(value);
}
}

15
tests/errors.test.ts Normal file
View file

@ -0,0 +1,15 @@
import {describe, expect, it} from "vitest";
import {InvalidTypeValueError, TypeError} from "../src/errors";
import {s} from "../src/library";
describe("errors", () => {
it("tests type error", () => {
expect((new TypeError(s.property.string().type)).message).toBe("Error in type StringType");
expect((new TypeError(s.property.string().type, "test")).message).toBe("Error in type StringType: test");
});
it("tests invalid type value error", () => {
expect((new InvalidTypeValueError(s.property.decimal().type, ["value"])).message).toBe("Error in type DecimalType: [\"value\"] is an invalid value");
expect((new InvalidTypeValueError(s.property.decimal().type, ["value"], "test")).message).toBe("Error in type DecimalType: test");
});
});

View file

@ -1,5 +1,5 @@
import {describe, expect, test} from "vitest";
import {ArrayType, s} from "../../../src/library";
import {ArrayType, InvalidTypeValueError, s} from "../../../src/library";
class TestModel
{
@ -122,4 +122,16 @@ describe("array type", () => {
expect(testProperty.type.clone(undefined)).toBe(undefined);
expect(testProperty.type.clone(null)).toBe(null);
});
test("invalid parameters types", () => {
expect(() => testProperty.type.serialize({} as any)).toThrowError(InvalidTypeValueError);
expect(() => testProperty.type.deserialize({} as any)).toThrowError(InvalidTypeValueError);
expect(() => testProperty.type.serializeDiff({} as any)).toThrowError(InvalidTypeValueError);
expect(() => testProperty.type.resetDiff({} as any)).not.toThrow();
expect(testProperty.type.hasChanged({} as any, {} as any)).toBeTruthy();
expect(testProperty.type.hasChanged(false as any, false as any)).toBeFalsy();
expect(testProperty.type.serializedHasChanged({} as any, {} as any)).toBeTruthy();
expect(testProperty.type.serializedHasChanged(false as any, false as any)).toBeFalsy();
expect(() => testProperty.type.clone({} as any)).toThrowError(InvalidTypeValueError);
});
});

View file

@ -1,5 +1,5 @@
import {describe, expect, test} from "vitest";
import {BooleanType, s, StringType} from "../../../src/library";
import {BooleanType, s} from "../../../src/library";
describe("boolean type", () => {
test("boolean type definition", () => {
@ -50,4 +50,19 @@ describe("boolean type", () => {
s.property.boolean().type.resetDiff(undefined);
s.property.boolean().type.resetDiff(null);
});
test("invalid parameters types", () => {
expect(s.property.boolean().type.serialize(1 as any)).toBeTruthy();
expect(s.property.boolean().type.serialize(0 as any)).toBeFalsy();
expect(s.property.boolean().type.deserialize(1 as any)).toBeTruthy();
expect(s.property.boolean().type.deserialize(0 as any)).toBeFalsy();
expect(s.property.boolean().type.serializeDiff(1 as any)).toBeTruthy();
expect(s.property.boolean().type.serializeDiff(0 as any)).toBeFalsy();
expect(() => s.property.boolean().type.resetDiff({} as any)).not.toThrow();
expect(s.property.boolean().type.hasChanged({} as any, {} as any)).toBeTruthy();
expect(s.property.boolean().type.hasChanged(false as any, false as any)).toBeFalsy();
expect(s.property.boolean().type.serializedHasChanged({} as any, {} as any)).toBeTruthy();
expect(s.property.boolean().type.serializedHasChanged(false as any, false as any)).toBeFalsy();
expect(s.property.boolean().type.clone({} as any)).toStrictEqual({});
});
});

View file

@ -1,5 +1,5 @@
import {describe, expect, test} from "vitest";
import {DateType, s} from "../../../src/library";
import {DateType, InvalidTypeValueError, s} from "../../../src/library";
describe("date type", () => {
const testDate = new Date();
@ -59,4 +59,16 @@ describe("date type", () => {
expect(clonedPropertyValue).toEqual(propertyValue);
}
});
test("invalid parameters types", () => {
expect(() => s.property.date().type.serialize({} as any)).toThrowError(InvalidTypeValueError);
expect(s.property.date().type.deserialize({} as any).getTime()).toBe(NaN);
expect(() => s.property.date().type.serializeDiff({} as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.date().type.resetDiff({} as any)).not.toThrow();
expect(s.property.date().type.hasChanged({} as any, {} as any)).toBeTruthy();
expect(s.property.date().type.hasChanged(false as any, false as any)).toBeFalsy();
expect(s.property.date().type.serializedHasChanged({} as any, {} as any)).toBeTruthy();
expect(s.property.date().type.serializedHasChanged(false as any, false as any)).toBeFalsy();
expect(s.property.date().type.clone({} as any)).toStrictEqual({});
});
});

View file

@ -1,5 +1,5 @@
import {describe, expect, test} from "vitest";
import {DecimalType, s} from "../../../src/library";
import {DecimalType, InvalidTypeValueError, s} from "../../../src/library";
describe("decimal type", () => {
test("decimal type definition", () => {
@ -44,4 +44,17 @@ describe("decimal type", () => {
s.property.decimal().type.resetDiff(undefined);
s.property.decimal().type.resetDiff(null);
});
test("invalid parameters types", () => {
expect(() => s.property.decimal().type.serialize({} as any)).toThrowError(InvalidTypeValueError);
expect(s.property.decimal().type.deserialize({} as any)).toBe(NaN);
expect(s.property.decimal().type.deserialize({} as any)).toBe(NaN);
expect(() => s.property.decimal().type.serializeDiff({} as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.decimal().type.resetDiff({} as any)).not.toThrow();
expect(s.property.decimal().type.hasChanged({} as any, {} as any)).toBeTruthy();
expect(s.property.decimal().type.hasChanged(false as any, false as any)).toBeFalsy();
expect(s.property.decimal().type.serializedHasChanged({} as any, {} as any)).toBeTruthy();
expect(s.property.decimal().type.serializedHasChanged(false as any, false as any)).toBeFalsy();
expect(s.property.decimal().type.clone({} as any)).toStrictEqual({});
});
});

View file

@ -1,5 +1,5 @@
import {describe, expect, test} from "vitest";
import {ModelType, s} from "../../../src/library";
import {InvalidTypeValueError, ModelType, s} from "../../../src/library";
class TestModel
{
@ -104,4 +104,29 @@ describe("model type", () => {
expect(s.property.model(testModel).type.clone(undefined)).toBe(undefined);
expect(s.property.model(testModel).type.clone(null)).toBe(null);
});
test("invalid parameters types", () => {
expect(() => s.property.model(testModel).type.serialize(5 as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.model(testModel).type.deserialize(5 as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.model(testModel).type.serializeDiff(5 as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.model(testModel).type.resetDiff(5 as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.model(testModel).type.hasChanged(5 as any, 5 as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.model(testModel).type.serializedHasChanged(5 as any, 5 as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.model(testModel).type.clone(5 as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.model(testModel).type.serialize([] as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.model(testModel).type.deserialize([] as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.model(testModel).type.serializeDiff([] as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.model(testModel).type.resetDiff([] as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.model(testModel).type.hasChanged(testModel.model(new TestModel()).instance, [] as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.model(testModel).type.serializedHasChanged({} as any, [] as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.model(testModel).type.clone([] as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.model(testModel).type.serialize(new class{} as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.model(testModel).type.serializeDiff(new class{} as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.model(testModel).type.resetDiff(new class{} as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.model(testModel).type.hasChanged(testModel.model(new TestModel()).instance, new class{} as any)).toThrowError(InvalidTypeValueError);
expect(s.property.model(testModel).type.serializedHasChanged({} as any, new class{} as any)).toBeFalsy();
expect(() => s.property.model(testModel).type.clone(new class{} as any)).toThrowError(InvalidTypeValueError);
});
});

View file

@ -1,5 +1,5 @@
import {describe, expect, test} from "vitest";
import {NumericType, s} from "../../../src/library";
import {InvalidTypeValueError, NumericType, s} from "../../../src/library";
describe("numeric type", () => {
test("numeric type definition", () => {
@ -44,4 +44,16 @@ describe("numeric type", () => {
s.property.numeric().type.resetDiff(undefined);
s.property.numeric().type.resetDiff(null);
});
test("invalid parameters types", () => {
expect(() => s.property.numeric().type.serialize({} as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.numeric().type.deserialize({} as any)).toThrowError(InvalidTypeValueError)
expect(() => s.property.numeric().type.serializeDiff({} as any)).toThrowError(InvalidTypeValueError);
expect(() => s.property.numeric().type.resetDiff({} as any)).not.toThrow();
expect(s.property.numeric().type.hasChanged({} as any, {} as any)).toBeTruthy();
expect(s.property.numeric().type.hasChanged(false as any, false as any)).toBeFalsy();
expect(s.property.numeric().type.serializedHasChanged({} as any, {} as any)).toBeTruthy();
expect(s.property.numeric().type.serializedHasChanged(false as any, false as any)).toBeFalsy();
expect(s.property.numeric().type.clone({} as any)).toStrictEqual({});
});
});

View file

@ -1,5 +1,5 @@
import {describe, expect, test} from "vitest";
import {NumericType, ObjectType, s, StringType} from "../../../src/library";
import {InvalidTypeValueError, NumericType, ObjectType, s, StringType} from "../../../src/library";
describe("object type", () => {
test("object type definition", () => {
@ -79,4 +79,22 @@ describe("object type", () => {
expect(testProperty.type.clone(undefined)).toBe(undefined);
expect(testProperty.type.clone(null)).toBe(null);
});
test("invalid parameters types", () => {
expect(() => testProperty.type.serialize(5 as any)).toThrowError(InvalidTypeValueError);
expect(() => testProperty.type.deserialize(5 as any)).toThrowError(InvalidTypeValueError);
expect(() => testProperty.type.serializeDiff(5 as any)).toThrowError(InvalidTypeValueError);
expect(() => testProperty.type.resetDiff(5 as any)).toThrowError(InvalidTypeValueError);
expect(() => testProperty.type.hasChanged(5 as any, 5 as any)).toThrowError(InvalidTypeValueError);
expect(() => testProperty.type.serializedHasChanged(5 as any, 5 as any)).toThrowError(InvalidTypeValueError);
expect(() => testProperty.type.clone(5 as any)).toThrowError(InvalidTypeValueError);
expect(() => testProperty.type.serialize([] as any)).toThrowError(InvalidTypeValueError);
expect(() => testProperty.type.deserialize([] as any)).toThrowError(InvalidTypeValueError);
expect(() => testProperty.type.serializeDiff([] as any)).toThrowError(InvalidTypeValueError);
expect(() => testProperty.type.resetDiff([] as any)).toThrowError(InvalidTypeValueError);
expect(() => testProperty.type.hasChanged({} as any, [] as any)).toThrowError(InvalidTypeValueError);
expect(() => testProperty.type.serializedHasChanged({} as any, [] as any)).toThrowError(InvalidTypeValueError);
expect(() => testProperty.type.clone([] as any)).toThrowError(InvalidTypeValueError);
});
});

View file

@ -44,4 +44,20 @@ describe("string type", () => {
s.property.string().type.resetDiff(undefined);
s.property.string().type.resetDiff(null);
});
test("invalid parameters types", () => {
const testDate = new Date();
expect(s.property.string().type.serialize({} as any)).toBe("[object Object]");
expect(s.property.string().type.serialize(2120 as any)).toBe("2120");
expect(s.property.string().type.serialize(testDate as any)).toBe(testDate.toString());
expect(s.property.string().type.deserialize({} as any)).toBe("[object Object]");
expect(s.property.string().type.deserialize(2120 as any)).toBe("2120");
expect(s.property.string().type.serializeDiff({} as any)).toBe("[object Object]");
expect(s.property.string().type.serializeDiff(2120 as any)).toBe("2120");
expect(s.property.string().type.hasChanged({} as any, {} as any)).toBeTruthy();
expect(s.property.string().type.hasChanged(false as any, false as any)).toBeFalsy();
expect(s.property.string().type.serializedHasChanged({} as any, {} as any)).toBeTruthy();
expect(s.property.string().type.serializedHasChanged(false as any, false as any)).toBeFalsy();
expect(s.property.string().type.clone({} as any)).toStrictEqual({});
});
});