Types
S7E provides a comprehensive type system to ensure type safety and enable powerful serialization features. This reference covers all the types, interfaces, and type definitions used throughout the library.
Core Types
ClassConstructor<T>
A type representing a class constructor that can create instances of type T
.
Definition
type ClassConstructor<T = any> =
| (new (...args: any[]) => T)
| (abstract new (...args: any[]) => T);
Usage
function deserialize<T>(type: ClassConstructor<T>, json: string): T {
// Implementation
}
// Examples
class User { }
abstract class Shape { }
const UserConstructor: ClassConstructor<User> = User;
const ShapeConstructor: ClassConstructor<Shape> = Shape;
TypeConstructor
A union type representing all valid type constructors for JSON properties.
Definition
type TypeConstructor =
| PrimitiveConstructor
| ClassConstructor;
Primitive Types
type PrimitiveConstructor =
| StringConstructor // String
| NumberConstructor // Number
| BooleanConstructor // Boolean
| DateConstructor; // Date
Usage
// Primitive types
@JsonProperty({ name: 'text', type: String })
public text: string;
@JsonProperty({ name: 'count', type: Number })
public count: number;
@JsonProperty({ name: 'active', type: Boolean })
public active: boolean;
@JsonProperty({ name: 'created', type: Date })
public created: Date;
// Custom class types
@JsonProperty({ name: 'user', type: User })
public user: User;
// Array types
@JsonProperty({ name: 'tags', type: [String] })
public tags: string[];
@JsonProperty({ name: 'users', type: [User] })
public users: User[];
PropertyMapping
Internal type used to map class property names to JSON property names.
Definition
interface PropertyMapping {
/** The TypeScript property name */
name: string;
/** The JSON property name */
jsonName: string;
}
Usage
This type is used internally by the metadata registry. You typically don't interact with it directly, but it's created when you use the @JsonProperty
decorator:
@JsonProperty({ name: 'user_name', type: String })
public userName: string;
// Creates: { name: 'userName', jsonName: 'user_name' }
Configuration Interfaces
JsonClassOptions
Configuration options for the @JsonClass
decorator.
Definition
interface JsonClassOptions {
/** Name for the JSON class (mandatory) */
name: string;
}
Properties
Property | Type | Required | Description |
---|---|---|---|
name | string | Yes | Unique identifier for the class used in polymorphic serialization |
Usage
@JsonClass({ name: 'User' })
class User {
// Implementation
}
@JsonClass({ name: 'AdminUser' })
class AdminUser extends User {
// Implementation
}
Guidelines
- Unique Names: Each class should have a unique name across your application
- Descriptive: Use clear, descriptive names that identify the class purpose
- Consistent: Follow a consistent naming convention (e.g., PascalCase)
- Stable: Avoid changing names after deployment as it affects serialized data compatibility
// Good examples
@JsonClass({ name: 'UserProfile' })
@JsonClass({ name: 'ShoppingCart' })
@JsonClass({ name: 'PaymentMethod' })
@JsonClass({ name: 'OrderItem' })
// Avoid
@JsonClass({ name: 'data' })
@JsonClass({ name: 'obj' })
@JsonClass({ name: 'temp' })
JsonPropertyOptions
Configuration options for the @JsonProperty
decorator.
Definition
interface JsonPropertyOptions {
/** The JSON property name (mandatory) */
name: string;
/** The type constructor or array of type constructors */
type?: TypeConstructor | [TypeConstructor];
/** Whether the property is optional (default: false) */
optional?: boolean;
}
Properties
Property | Type | Required | Default | Description |
---|---|---|---|---|
name | string | Yes | - | JSON property name for serialization |
type | TypeConstructor | [TypeConstructor] | No | Inferred | Type constructor for validation and deserialization |
optional | boolean | No | false | Whether the property can be omitted from JSON |
Usage Examples
Basic Properties
@JsonProperty({ name: 'userId', type: Number })
public id: number;
@JsonProperty({ name: 'userName', type: String })
public name: string;
@JsonProperty({ name: 'isActive', type: Boolean })
public active: boolean;
Optional Properties
@JsonProperty({ name: 'email', type: String, optional: true })
public email?: string;
@JsonProperty({ name: 'phone', type: String, optional: true })
public phoneNumber?: string;
Array Properties
@JsonProperty({ name: 'tags', type: [String] })
public tags: string[];
@JsonProperty({ name: 'scores', type: [Number] })
public scores: number[];
@JsonProperty({ name: 'addresses', type: [Address] })
public addresses: Address[];
Custom Object Properties
@JsonProperty({ name: 'profile', type: UserProfile })
public profile: UserProfile;
@JsonProperty({ name: 'settings', type: UserSettings, optional: true })
public settings?: UserSettings;
Type Validation
S7E performs runtime type validation during deserialization to ensure data integrity.
Validation Rules
Primitive Types
// String validation
@JsonProperty({ name: 'text', type: String })
public text: string;
// Accepts: "hello", "123", ""
// Rejects: 123, true, null, undefined, {}
// Number validation
@JsonProperty({ name: 'count', type: Number })
public count: number;
// Accepts: 42, 3.14, 0, -10
// Rejects: "123", true, null, undefined, {}
// Boolean validation
@JsonProperty({ name: 'active', type: Boolean })
public active: boolean;
// Accepts: true, false
// Rejects: "true", 1, 0, null, undefined, {}
// Date validation
@JsonProperty({ name: 'created', type: Date })
public created: Date;
// Accepts: "2025-01-29T00:00:00Z", "2025-01-29"
// Rejects: "invalid date", 123, true, null, undefined
Array Validation
@JsonProperty({ name: 'tags', type: [String] })
public tags: string[];
// Accepts: ["tag1", "tag2"], []
// Rejects: "not an array", [1, 2, 3], [true, false]
@JsonProperty({ name: 'users', type: [User] })
public users: User[];
// Validates each array element as User instance
Optional Property Validation
@JsonProperty({ name: 'optional', type: String, optional: true })
public optional?: string;
// Accepts: "value", undefined (missing from JSON)
// Rejects: null, 123, true (if present, must be valid type)
Custom Type Validation
For complex validation scenarios, implement validation in static factory methods:
@JsonClass({ name: 'ValidatedUser' })
class ValidatedUser {
@JsonProperty({ name: 'email', type: String })
public email: string;
@JsonProperty({ name: 'age', type: Number })
public age: number;
public static fromJson(json: string): ValidatedUser {
const user = S7e.deserialize(ValidatedUser, json);
// Custom validation
if (!user.email.includes('@')) {
throw new Error('Invalid email format');
}
if (user.age < 0 || user.age > 150) {
throw new Error('Age must be between 0 and 150');
}
return user;
}
}
Type Guards and Utility Types
Type Guards
S7E doesn't export type guards directly, but you can create your own:
function isUser(obj: any): obj is User {
return obj instanceof User &&
typeof obj.id === 'number' &&
typeof obj.name === 'string';
}
function isUserArray(obj: any): obj is User[] {
return Array.isArray(obj) && obj.every(isUser);
}
// Usage
const data = S7e.deserialize(User, jsonString);
if (isUser(data)) {
// TypeScript knows data is User
console.log(data.name);
}
Utility Types
DeserializationResult
Create a utility type for safe deserialization:
type DeserializationResult<T> =
| { success: true; data: T }
| { success: false; error: string };
function safeDeserialize<T>(
type: ClassConstructor<T>,
json: string
): DeserializationResult<T> {
try {
const data = S7e.deserialize(type, json);
return { success: true, data };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
SerializableClass
Define a type for classes that can be serialized:
type SerializableClass<T = any> = ClassConstructor<T> & {
prototype: T;
};
function isSerializable<T>(type: ClassConstructor<T>): type is SerializableClass<T> {
// Check if class has @JsonClass decorator
return MetadataRegistry.isJsonClass(type);
}
TypeScript Configuration
For optimal type safety with S7E, configure your TypeScript project correctly:
tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022", "DOM"],
"module": "ESNext",
"moduleResolution": "node",
"strict": true,
"exactOptionalPropertyTypes": true,
"noUncheckedIndexedAccess": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"useDefineForClassFields": false
}
}
Key Options for S7E
experimentalDecorators: true
- Required for decorator supportemitDecoratorMetadata: true
- Required for metadata emissionstrict: true
- Enables all strict type checkingexactOptionalPropertyTypes: true
- Ensures proper optional property handlinguseDefineForClassFields: false
- Maintains compatibility with decorators
Advanced Type Patterns
Generic Serializable Classes
@JsonClass({ name: 'Result' })
class Result<T> {
@JsonProperty({ name: 'success', type: Boolean })
public success: boolean;
@JsonProperty({ name: 'data', type: Object, optional: true })
public data?: T;
@JsonProperty({ name: 'error', type: String, optional: true })
public error?: string;
public static success<T>(data: T): Result<T> {
const result = new Result<T>();
result.success = true;
result.data = data;
return result;
}
public static error<T>(error: string): Result<T> {
const result = new Result<T>();
result.success = false;
result.error = error;
return result;
}
}
Conditional Types
type SerializedType<T> = T extends string
? string
: T extends number
? number
: T extends boolean
? boolean
: T extends Date
? string
: T extends Array<infer U>
? SerializedType<U>[]
: T extends object
? Record<string, unknown>
: never;
// Example usage
type SerializedUser = SerializedType<User>;
// Results in an object type with serialized property types
Mapped Types
type JsonPropertyNames<T> = {
[K in keyof T]: T[K] extends { name: string } ? T[K]['name'] : never;
}[keyof T];
// Extract JSON property names from a class
type UserJsonProperties = JsonPropertyNames<User>;
Type Compatibility
Backward Compatibility
S7E maintains type compatibility across versions:
// Version 1.0
@JsonClass({ name: 'User' })
class User {
@JsonProperty({ name: 'id', type: Number })
public id: number;
}
// Version 1.1 - Adding optional property (backward compatible)
@JsonClass({ name: 'User' })
class User {
@JsonProperty({ name: 'id', type: Number })
public id: number;
@JsonProperty({ name: 'email', type: String, optional: true })
public email?: string;
}
Forward Compatibility
Design classes for forward compatibility:
@JsonClass({ name: 'ExtensibleUser' })
class ExtensibleUser {
@JsonProperty({ name: 'id', type: Number })
public id: number;
@JsonProperty({ name: 'name', type: String })
public name: string;
// Reserved for future use
@JsonProperty({ name: 'metadata', type: Object, optional: true })
public metadata?: Record<string, unknown>;
}
Related APIs
- Decorators - Using types with @JsonClass and @JsonProperty
- S7e Class - Methods that use these types
- Advanced Features - Complex type scenarios