diff --git a/src/Framework/Framework/Resources/Scripts/global-declarations.ts b/src/Framework/Framework/Resources/Scripts/global-declarations.ts index 848700e9fe..e875e05ef8 100644 --- a/src/Framework/Framework/Resources/Scripts/global-declarations.ts +++ b/src/Framework/Framework/Resources/Scripts/global-declarations.ts @@ -248,16 +248,19 @@ type TypeMap = { } type DynamicTypeMetadata = { + debugName?: string, type: "dynamic" } type ObjectTypeMetadata = { type: "object", + debugName?: string, properties: { [prop: string]: PropertyMetadata } } type EnumTypeMetadata = { type: "enum", + debugName?: string, values: { [name: string]: number }, isFlags?: boolean } diff --git a/src/Framework/Framework/Resources/Scripts/metadata/coercer.ts b/src/Framework/Framework/Resources/Scripts/metadata/coercer.ts index a7e58b4bf9..6d83ed6e8b 100644 --- a/src/Framework/Framework/Resources/Scripts/metadata/coercer.ts +++ b/src/Framework/Framework/Resources/Scripts/metadata/coercer.ts @@ -3,7 +3,7 @@ import { CoerceError } from "../shared-classes"; import { keys } from "../utils/objects"; import { tryCoerceEnum } from "./enums"; import { primitiveTypes } from "./primitiveTypes"; -import { getObjectTypeInfo, getTypeInfo } from "./typeMap"; +import { formatTypeName, getObjectTypeInfo, getTypeInfo } from "./typeMap"; /** * Validates type of value @@ -45,7 +45,7 @@ export function tryCoerce(value: any, type: TypeDefinition | null | undefined, o } } } - return new CoerceError(`Unsupported type metadata ${JSON.stringify(type)}!`); + return new CoerceError(`Unsupported type metadata ${formatTypeName(type)}!`); } const result = core(); @@ -100,7 +100,7 @@ function tryCoerceArray(value: any, innerType: TypeDefinition, originalValue: an return { value: items, wasCoerced: true }; } } - return new CoerceError(`Value '${JSON.stringify(value)}' is not an array of type '${JSON.stringify(innerType)}'.`); + return new CoerceError(`Value '${JSON.stringify(value)}' is not an array of type '${formatTypeName(innerType)}'.`); } function tryCoercePrimitiveType(value: any, type: string): CoerceResult { diff --git a/src/Framework/Framework/Resources/Scripts/metadata/typeMap.ts b/src/Framework/Framework/Resources/Scripts/metadata/typeMap.ts index cb6052aa8c..7246a989d4 100644 --- a/src/Framework/Framework/Resources/Scripts/metadata/typeMap.ts +++ b/src/Framework/Framework/Resources/Scripts/metadata/typeMap.ts @@ -63,3 +63,26 @@ export function areObjectTypesEqual(currentValue: any, newVal: any): boolean { } return false; } + + +export function formatTypeName(type: TypeDefinition, prefix = "", suffix = "") { + if (!compileConstants.debug) + return JSON.stringify(type) + + if (typeof type === "string") { + let debugName = types[type]?.debugName + if (debugName) + return `${prefix}${debugName}${suffix} (${prefix}${type}${suffix})` + else + return prefix + type + suffix + } + if (Array.isArray(type)) { + return formatTypeName(type[0], prefix, "[]" + suffix) + } + if (type.type == "nullable") { + return formatTypeName(type.inner, prefix, "?" + suffix) + } + if (type.type == "dynamic") { + return prefix + "dynamic" + suffix + } +} diff --git a/src/Framework/Framework/Resources/Scripts/state-manager.ts b/src/Framework/Framework/Resources/Scripts/state-manager.ts index 3dc584242b..737ecdd02f 100644 --- a/src/Framework/Framework/Resources/Scripts/state-manager.ts +++ b/src/Framework/Framework/Resources/Scripts/state-manager.ts @@ -3,7 +3,7 @@ import { createArray, defineConstantProperty, isPrimitive, keys } from "./utils/objects"; import { DotvvmEvent } from "./events"; import { extendToObservableArrayIfRequired } from "./serialization/deserialize" -import { areObjectTypesEqual, getObjectTypeInfo } from "./metadata/typeMap"; +import { areObjectTypesEqual, formatTypeName, getObjectTypeInfo } from "./metadata/typeMap"; import { coerce } from "./metadata/coercer"; import { patchViewModel } from "./postback/updater"; import { hackInvokeNotifySubscribers } from "./utils/knockout"; @@ -166,7 +166,7 @@ class FakeObservableObject implements UpdatableObjectExtension } } } else if (!isDynamic && p.indexOf("$") !== 0) { - logWarning("state-manager", `Unknown property '${p}' set on an object of type ${typeId}.`); + logWarning("state-manager", `Unknown property '${p}' set on an object of type ${formatTypeName(typeId)}.`); } this[internalPropCache][p] = newObs