@polymorphicType / @polymorphicId
Declares polymorphic associations — a single model that can belong to multiple other models. Common patterns: comments on posts or users, images on products or reviews, likes on any content.
Syntax
src/interfaces.ts
interface Comment {
id: number;
body: string;
// @polymorphicType — stores the related model name (e.g. "Post", "User")
commentableType: string;
// @polymorphicId — stores the related record's primary key
commentableId: number;
createdAt: string;
updatedAt: string;
}Usage
src/auth.ts
// Create polymorphic comments
await Comment.insert({
body: "Great post!",
commentableType: "Post",
commentableId: postId,
});
await Comment.insert({
body: "Nice user!",
commentableType: "User",
commentableId: userId,
});
// Resolve the parent — morphTo()
const comment = await Comment.get({ id: 1 });
const parent = await Comment.morphTo();
// Returns the Post or User instance that this comment belongs to
// The morphTo method reads commentableType + commentableId,
// looks up the matching model, and returns the related record.How It Works
| Field | Annotation | Purpose |
|---|---|---|
commentableType | @polymorphicType | Stores the model name (e.g. "Post", "User") |
commentableId | @polymorphicId | Stores the related record's primary key value |
The schema generator detects both annotations and registers the polymorphic relationship. morphTo() uses the type + id to dynamically resolve the parent model at runtime.
Errors
| Error | Cause | Fix |
|---|---|---|
Unknown polymorphic type: "X" | commentableType value doesn't match any defined model | Ensure the type value matches a model name exactly |
Polymorphic id is null | commentableId is NULL in the database | Always provide both type and id together |
morphTo() returned null | The referenced record doesn't exist (deleted or invalid id) | Use optional chaining: const parent = await comment.morphTo() |
Conventions
- Name the type field as
<relation>Typeand the id field as<relation>Id(e.g.imageableType+imageableId,likableType+likableId) - The type value must match a registered model name exactly (case-sensitive)
- Polymorphic relations don't use foreign key constraints — the referenced record could be deleted
- Always check if
morphTo()returnsnull— the parent may have been deleted