[data-reveal]{opacity:1!important;transform:none!important}
Core

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

ParameterTypeDefaultDescription
targetU-The object to retrieve or create metadata for
metaClass<T, [U]> & { key: symbol }-A metadata class with a static key symbol
inheritbooleantrueWhether 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