IonIon
Packages
  • next
  • current
Changelog
GitHub
Packages
  • next
  • current
Changelog
GitHub
  • Version 0.x

    • Release Notes
    • Upgrade Guide
    • Contribution Guide
    • Security Policy
    • Code of Conduct
    • Origin
  • Packages

    • Introduction
    • Container

      • Introduction
      • Prerequisites
      • How to install
      • Container Instance
      • Bindings
      • Dependencies
      • Resolving
      • Contextual Bindings
    • Contracts

      • Introduction
      • How to install
    • Support

      • Introduction
      • How to install
      • Arrays

        • About Arrays
        • Includes All
        • Includes Any
        • Is Array Like
        • Is Concat Spreadable
        • Is Safe Array Like
        • Is Typed Array
        • Merge
      • Concerns

        • About Concerns
        • Prerequisites
        • Concern Class
        • Using Concerns
        • Aliases
        • Conflict Resolution
        • Booting
        • Hooks
        • Edge Cases
        • JSDoc
      • Exceptions

        • About Exceptions
        • Configure Custom Error
        • Configure Stack Trace
        • Get Error Message
        • Custom Errors
      • Facades

        • About Facades
      • Meta

        • About Meta
        • Prerequisites
        • Supported Elements
        • Set & Get
        • Inheritance
        • Outside Changes
        • TC39 Proposal
        • Target Meta
      • Mixins

        • About Mixins
        • New Mixin
        • Apply Mixins
        • Instanceof
        • Inheritance
        • Onward
      • Object

        • About Objects
        • Forget
        • Forget All
        • Get
        • Has
        • Has All
        • Has Any
        • Has Unique ID
        • Is Cloneable
        • Is Populatable
        • Isset
        • Merge
        • Populate
        • Set
        • Unique ID
      • Reflections

        • About reflections
        • Assert Has Prototype Prop.
        • Class Looks Like
        • Class Own Keys
        • Get All Parents Of Class
        • Get Class Prop. Descriptor
        • Get Class Prop. Descriptors
        • Get Constructor Name
        • Get Name Or Desc. Tag
        • Get Parent Of Class
        • Has All Methods
        • Has Method
        • Has Prototype Property
        • Is Callable
        • Is Class Constructor
        • Is Class Method Reference
        • Is Constructor
        • Is Key Safe
        • Is Key Unsafe
        • Is Method
        • Is Subclass
        • Is Subclass Or Looks Like
        • Is WeakKind
      • Misc

        • About Misc.
        • Desc. Tag
        • Empty
        • Is Key
        • Is Primitive
        • Is Property Key
        • Isset
        • Merge Keys
        • To Weak Ref.
      • Callback Wrapper
    • Vuepress Utils

      • Introduction
      • How to install
      • Navigation

        • Archive
      • Plugins

        • Last Updated
      • Components

        • Version Disclaimer
    • XYZ (test package)

Target Meta Available since v0.7

The targetMeta() decorator offers the ability to associate metadata directly with a class instance or class method reference. This can be useful in situations when you do not know the class that owns the metadata.

Behind the scene, targetMeta() uses the meta() decorator and stores a reference to the target that is decorated inside a WeakMap.

  • Supported Elements
  • Class Instance
  • Method Reference
  • Inheritance
    • Static Methods

Supported Elements

Unlike the meta() decorator, targetMeta() only supports the following elements:

  • class
  • method

Class Instance

The following shows how to define target meta for a class and retrieve it.

import { targetMeta, getTargetMeta } from '@aedart/support/meta';

@targetMeta('description', { type: 'Search Service', alias: 'Location Sercher' })
class LocationSearcherService {}

const instance = new LocationSearcherService();

// ...later in your application...
getTargetMeta(instance, 'description')?.type; // Search Service

Method Reference

The following shows how to define target meta for a class method and retrieve it.

import { targetMeta, getTargetMeta } from '@aedart/support/meta';

class LocationSearcherService {

    @targetMeta('dependencies', [ 'httpClient' ])    
    search(apiClient) {}
}

const instance = new LocationSearcherService();

// ...later in your application...
getTargetMeta(instance.search, 'dependencies'); // [ 'httpClient' ]

Inheritance

Target meta is automatically inherited by subclasses and can also be overwritten, similar to that of the meta() decorator.

Example: classes

import {targetMeta, getTargetMeta} from '@aedart/support/meta';

@meta('service_alias', 'locationSearcher')
class Service {}

class CitySearcher extends Service {}

const instance = new CitySearcher();

// ...later in your application...
getTargetMeta(instance, 'service_alias'); // locationSearcher

Example: methods

import {targetMeta, getTargetMeta} from '@aedart/support/meta';

class Service {

    @targetMeta('dependencies', [ 'countrySearchApiClient' ])
    search(apiClient) {
        // ...not shown...
    }
}

class CountrySearcher extends Service {
    // ... not method overwrite here...
}

class CitySearcher extends Service {

    @targetMeta('dependencies', [ 'citySearchApiClient' ])
    search(apiClient) {
        // ...not shown...
    }
}

const instanceA = new Service();
const instanceB = new CountrySearcher();
const instanceC = new CitySearcher();

// ...later in your application...
getTargetMeta(instanceA.search, 'dependencies'); // [ 'countrySearchApiClient' ]
getTargetMeta(instanceB.search, 'dependencies'); // [ 'countrySearchApiClient' ]
getTargetMeta(instanceC.search, 'dependencies'); // [ 'citySearchApiClient' ]

Static Methods

Inheritance for static methods works a bit differently. By default, any subclass will automatically inherit target metadata, even for static methods. However, if you overwrite the given static method, the metadata is lost.

Limitation

When a static method is overwritten, the parent's "target" metadata cannot be obtained due to a general limitation of the meta() decorator. The decorator has no late this binding available to the overwritten static method. This makes it impossible to associate the overwritten static method with metadata from the parent.

Example: inheritance for static methods

import {targetMeta, getTargetMeta} from '@aedart/support/meta';

class Service {

    @targetMeta('dependencies', [ 'xmlClient' ])
    static search(client) {
        // ...not shown...
    }
}

class CountrySearcher extends Service {
    // ... not method overwrite here...
}

class CitySearcher extends Service {
    
    // Overwite of static method - target meta is lost
    static search(client) {}
}

// ...later in your application...
getTargetMeta(CountrySearcher.search, 'dependencies'); // [ 'xmlClient' ]
getTargetMeta(CitySearcher.search, 'dependencies'); // undefined

To overcome the above shown issue, you can use the inheritTargetMeta() decorator. It forces the static method to "copy" metadata from its parent, if available.

Example: force inheritance for static methods

import {
    targetMeta,
    getTargetMeta,
    inheritTargetMeta
} from '@aedart/support/meta';

class Service {

    @targetMeta('dependencies', [ 'xmlClient' ])
    static search(client) {
        // ...not shown...
    }
}

class CountrySearcher extends Service {
    // ... not method overwrite here...
}

class CitySearcher extends Service {
    
    @inheritTargetMeta()
    static search(client) {}
}

// ...later in your application...
getTargetMeta(CountrySearcher.search, 'dependencies'); // [ 'xmlClient' ]
getTargetMeta(CitySearcher.search, 'dependencies'); // [ 'xmlClient' ]
Edit page
Last Updated: 3/1/2024, 10:25:21 AM
Contributors: alin
Prev
TC39 Proposal