Metadata
Overview
The GetMetadata function provides a reflection-based metadata system built on top of the reflect-metadata library. It retrieves or creates metadata instances associated with target objects, supporting inheritance through the prototype chain.
Import
import { GetMetadata } from "@antelopejs/interface-core";
GetMetadata
function GetMetadata<T, U>(target: U, meta: Class<T, [U]> & { key: symbol }, inherit?: boolean): T
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
target | U | - | The object to retrieve or create metadata for |
meta | Class<T, [U]> & { key: symbol } | - | A metadata class with a static key symbol |
inherit | boolean | true | Whether to inherit metadata from the prototype chain |
Return value
Returns the metadata instance of type T associated with the target.
Define a metadata class
A metadata class must have a static key property (a Symbol) and accept the target object as a constructor argument.
class RouteMetadata {
static key = Symbol("RouteMetadata");
public routes: Map<string, string> = new Map();
constructor(_target: any) {
// Initialize metadata for the target
}
}
Retrieve metadata
import { GetMetadata } from "@antelopejs/interface-core";
class UserController {
getUser() {}
listUsers() {}
}
const meta = GetMetadata(UserController.prototype, RouteMetadata);
meta.routes.set("getUser", "/users/:id");
meta.routes.set("listUsers", "/users");
Calling GetMetadata multiple times with the same target and metadata class returns the same instance. The metadata is stored on the target using Reflect.defineMetadata.
Inheritance
When inherit is true (the default), GetMetadata walks the prototype chain to find parent metadata. If the metadata class defines an inherit method, that method is called with the parent metadata. Otherwise, properties from the parent are copied to the child metadata where they do not already exist.
class ControllerMeta {
static key = Symbol("ControllerMeta");
public middleware: string[] = [];
constructor(_target: any) {}
inherit(parent: ControllerMeta) {
this.middleware = [...parent.middleware];
}
}
class BaseController {}
const baseMeta = GetMetadata(BaseController.prototype, ControllerMeta);
baseMeta.middleware.push("auth");
class AdminController extends BaseController {}
const adminMeta = GetMetadata(AdminController.prototype, ControllerMeta);
// adminMeta.middleware contains ["auth"] (inherited from BaseController)
adminMeta.middleware.push("adminOnly");
// adminMeta.middleware is now ["auth", "adminOnly"]
// baseMeta.middleware remains ["auth"]
Without a custom inherit method, properties are shallow-copied from parent to child using Object.getOwnPropertyNames, but only for keys that do not already exist on the child metadata instance.
Disable inheritance
Pass false as the third argument to prevent prototype chain traversal:
const meta = GetMetadata(target, RouteMetadata, false);
Next steps
- Decorators - Combine metadata with decorator factories
- Modules - Module lifecycle events and management