Basic Usage
This example demonstrates the fundamental concepts of QuickModel with simple, practical code.
Problem
You're fetching user data from an API that returns dates as ISO strings and you want to work with actual Date objects in your code.
Solution
Use QuickModel to automatically transform the data:
import { QModel, Quick } from 'quickmodel';
// 1. Define your interface (API format)
interface IUser {
id: number;
name: string;
email: string;
createdAt: string; // ISO date string from API
updatedAt: string; // ISO date string from API
}
// 2. Create your model with transformations
@Quick({
createdAt: Date,
updatedAt: Date,
})
class User extends QModel<IUser> {
declare id: number;
declare name: string;
declare email: string;
declare createdAt: Date;
declare updatedAt: Date;
}
// 3. Use it with API data
const apiResponse = {
id: 1,
name: 'John Doe',
email: 'john@example.com',
createdAt: '2026-01-10T10:00:00.000Z',
updatedAt: '2026-01-10T15:30:00.000Z',
};
const user = new User(apiResponse);
// 4. Work with transformed types
console.log(user.createdAt instanceof Date); // true
console.log(user.createdAt.getFullYear()); // 2026
// 5. Serialize back to JSON
const plain = user.$qSerialize();
console.log(plain.createdAt); // '2026-01-10T10:00:00.000Z'Step-by-Step Explanation
1. Define the Interface
The interface represents the data format from your API (JSON-compatible types):
interface IUser {
id: number;
name: string;
email: string;
createdAt: string; // Dates come as strings from JSON
updatedAt: string;
}2. Apply the @Quick Decorator
Specify which properties need transformation:
@Quick({
createdAt: Date, // Transform string → Date
updatedAt: Date // Transform string → Date
})3. Declare Properties
Use declare to define runtime types without generating code:
class User extends QModel<IUser> {
declare id: number; // No transformation needed
declare name: string; // No transformation needed
declare email: string; // No transformation needed
declare createdAt: Date; // Will be transformed
declare updatedAt: Date; // Will be transformed
}4. Create Instances
Pass API data directly to the constructor:
const user = new User(apiResponse);
// All transformations happen automatically5. Serialize Back
Use serialize() to get a plain object (for property access, REST bodies, etc.), or toJSON() for a JSON string:
const plain = user.$qSerialize();
// Dates are converted back to ISO strings
// Use user.toJSON() for the raw JSON stringWorking with Arrays
Transform arrays of data:
interface IPost {
id: string;
title: string;
publishedAt: string;
tags: string[];
}
@Quick({
publishedAt: Date,
tags: Set, // Transform array → Set
})
class Post extends QModel<IPost> {
declare id: string;
declare title: string;
declare publishedAt: Date;
declare tags: Set<string>;
}
const posts = [
{
id: '1',
title: 'First Post',
publishedAt: '2026-01-01',
tags: ['typescript', 'node'],
},
{
id: '2',
title: 'Second Post',
publishedAt: '2026-01-02',
tags: ['javascript', 'web'],
},
];
// Transform all posts
const transformedPosts = posts.map((post) => new Post(post));
console.log(transformedPosts[0].publishedAt instanceof Date); // true
console.log(transformedPosts[0].tags instanceof Set); // trueArrays of Transformed Types
Use bracket notation for arrays of transformed types:
interface ICalendar {
name: string;
events: string[]; // Array of ISO date strings
}
@Quick({
events: [Date], // Transform to Date[]
})
class Calendar extends QModel<ICalendar> {
declare name: string;
declare events: Date[];
}
const calendar = new Calendar({
name: 'My Calendar',
events: [
'2026-01-10T10:00:00.000Z',
'2026-01-15T14:00:00.000Z',
'2026-01-20T09:00:00.000Z',
],
});
console.log(calendar.events[0] instanceof Date); // true
console.log(calendar.events.length); // 3Using create() Method
Alternative factory method for creating instances:
const user = User.create({
id: 1,
name: 'Jane Doe',
email: 'jane@example.com',
createdAt: '2026-01-10',
updatedAt: '2026-01-10',
});
console.log(user instanceof User); // trueMock Generation
Generate test data easily:
// Single mock with random values
const mockUser = User.mock().random();
console.log(mockUser.createdAt instanceof Date); // true ✅ respects transformations
// Multiple random mocks
const mockUsers = User.mock().array(5);
console.log(mockUsers.length); // 5
// Mock with overrides on specific fields
const customUser = User.mock().random({
name: 'Test User',
email: 'test@example.com',
});
console.log(customUser.name); // 'Test User'
// Empty mock
const emptyUser = User.mock().empty();
// Predictable mock (for snapshots)
const sampleUser = User.mock().sample();Complete Example
Here's a complete example with all features:
import { QModel, Quick } from 'quickmodel';
interface IUser {
id: number;
name: string;
email: string;
createdAt: string;
updatedAt: string;
tags: string[];
}
@Quick({
createdAt: Date,
updatedAt: Date,
tags: Set,
})
class User extends QModel<IUser> {
declare id: number;
declare name: string;
declare email: string;
declare createdAt: Date;
declare updatedAt: Date;
declare tags: Set<string>;
}
// Simulate API response
const apiData = {
id: 1,
name: 'John Doe',
email: 'john@example.com',
createdAt: '2026-01-10T10:00:00.000Z',
updatedAt: '2026-01-10T15:30:00.000Z',
tags: ['developer', 'typescript', 'node'],
};
// Create model instance
const user = new User(apiData);
// Work with transformed types
console.log('User created:', user.createdAt.toLocaleDateString());
console.log('Tags:', Array.from(user.tags).join(', '));
// Modify data
user.name = 'Jane Doe';
user.tags.add('quickmodel');
// Serialize back to JSON string (ready for fetch body, WebSockets, etc.)
const jsonStr = user.toJSON();
console.log('Updated data:', jsonStr);
// Generate mocks for testing
const testUsers = User.mock().array(3, 'random', () => ({ tags: ['test'] }));
console.log('Test users:', testUsers.length);Best Practices
1. Use declare for Properties
// ✅ Good - no runtime code
declare;
createdAt: Date;
// ❌ Avoid - generates unnecessary code
createdAt: Date = new Date();2. Be Explicit with Transformations
// ✅ Good - explicit transformations
@Quick({
createdAt: Date,
tags: Set
})
// ❌ Bad - missing transformations
@Quick() // Dates won't transform!3. Use Bracket Notation for Arrays
// ✅ Good - clear array syntax
@Quick({
dates: [Date]
})
// ❌ Bad - ambiguous
@Quick({
dates: Date // Single Date or Date[]?
})Next Steps
- API Models - Integrate with REST APIs
- Complex Types - Advanced transformations
- Nested Models - Work with nested data