@decorators/alias@0.1.2
Stage 3 Decorator factory to help you painlessly create aliases between different class members. Supports class methods, getters, setters, fields, and accessors.
alias
The @decorators/alias
package provides a simple decorator factory named
@alias
, which allows you to alias one class member to another with zero
configuration. It supports aliasing class fields, accessors, methods, getters,
and setters. Compatible with both the instance side and the static side of any
TypeScript/JavaScript class.
Getting Started
All @decorators/*
packages are published exclusively to JSR.io,
a new registry for TypeScript and JavaScript developers, with a keen focus on
performance, security, and compatibility.
1. Install
deno add @decorators/alias
jsr add @decorators/alias
Additional Package Managers
bunx jsr add @decorators/alias
npx jsr add @decorators/alias
pnpx jsr add @decorators/alias
yarn dlx jsr add @decorators/alias
Installation Requirements
This decorator is developed using the latest iteration of the
TC39 Decorators Proposal; these are commonly referred to as "Stage 3" or
"ES" Decorators, to distinguish them from the legacy TypeScript decorators
that are enabled/disabled via the experimentalDecorators
compiler flag.
Stage 3 decorators do not require any special configuration to use - they are enabled by default in TypeScript 5.0+ and Deno 1.40.0+. If you're using an older version of TypeScript, you should consider upgrading to the latest version to take advantage of this feature.
Deno recently rolled out support for Stage 3 Decorators in the
1.40.0
release. It's the first runtime to support this feature out of the
box, and is my personal choice for TypeScript development. If you're not already
using Deno, I highly recommend giving it a try - it's a fantastic runtime for
beginners and experts alike.
2. Enjoy!
import { alias } from "@decorators/alias"; class Example { declare private hello: this["greet"]; declare private welcome: this["greet"]; private greeting = "Hello World"; @alias.for("greeting") private message!: string; @alias("hello", "welcome") greet() { return this.message; } }
Warning: Please ensure the
experimentalDecorators
option is disabled in yourtsconfig.json
ordeno.json
file'scompilerOptions
section.This package will not work if legacy TypeScript decorators are enabled.
API
There are two different approaches to creating aliases with this package, both
of which are available from the same named import, alias
.
alias
The first is to use @alias
directly on a class member you wish to alias, and
provide it with the name(s) of the alias(es) it should create to that member.
This allows you to create any number of aliases for a given class member, with
each alias name passed as an argument to the decorator factory.
Usage
class A { // these are important! declare b: this["a"]; declare c: this["a"]; @alias("b", "c") a() { // ... } }
Signature
export function alias< Aliases extends readonly PropertyKey[], This extends object = object, Value = unknown, >(...aliases: Aliases): { (target: unknown, context: DecoratorContext): void; };
This signature is in a simplified form for the sake of brevity. See the source code in
mod.ts
for the actual function signature as it is used in the implementation.
Parameters
Name | Info |
---|---|
...aliases |
The names of the aliases to create for the target member. |
Returns
This decorator factory returns a decorator function that can be applied to any
class member type, including fields, accessors, methods, getters, and setters.
It cannot be used on the class itself. The decorator it returns does not
return a replacement member, but instead leverages initialization side-effects
via the addInitializer
API, creating the alias(es) at initialization time.
Example
Take note of the logical flow in this approach, demonstrated below, where the
aliases are defined on the original member that is being decorated. You
can think of it in natural language as
"The 'greeting' field is also aliased as 'message'."
, or
"The 'greet' method is also aliased as 'hello' and 'welcome'."
.
import { alias } from "@decorators/alias"; class Example { declare private message: string; declare private hello: this["greet"]; declare private welcome: this["greet"]; @alias("message") private greeting = "Hello World"; @alias("hello", "welcome") greet() { return this.message; } } const example = new Example(); // The original method: console.log(example.greet()); // "Hello World" // The aliases to that method: console.log(example.hello()); // "Hello World" console.log(example.welcome()); // "Hello World" console.log(example.hello === example.greet); // true
Note: notice the property declarations in the following example. These ensure the TypeScript compiler recognizes each alias as a valid member of the class. If they were elided,
tsc
would raise compile errors complaining about non-existent properties.
alias.for
The second approach to aliasing class members with this package is to use the
@alias.for
method. Similar to the @alias
function, this is also
a decorator factory, but differs in that applied to the alias itself, providing
it with the name of the member it should point to. This accepts only one
argument, which must be the name of another existing member of the class.
Usage
class Hi { message = "Hello World"; greet() { return this.message; } @alias.for("greet") // source: greet, target: hello hello!: this["greet"]; // this is defined at initialization @alias.for("greet") // source: greet, target: welcome welcome(): string { // this is overridden at initialization return this.greet(); } }
Signature
alias.for = function<Source extends PropertyKey>(source: Source): { (target: unknown, context: DecoratorContext): void; };
Parameters
Name | Info |
---|---|
source |
The name of the class member to alias with the decorated alias. |
Returns
This decorator factory returns a decorator that can be applied to any class
member type, including fields, accessors, methods, getters, and setters. It
cannot be used on the class itself. The decorator it returns does not
return a replacement member (except when used on a field/accessor), but instead
leverages initialization side-effects via the addInitializer
API, creating the
alias(es) at initialization time.
Example
import { alias } from "@decorators/alias"; class Example { private greeting = "Hello World"; @alias.for("greeting") private message!: string; greet() { return this.message; } @alias.for("greet") hello!: this["greet"]; @alias.for("greet") welcome(): string { return this.greet(); } } const example = new Example(); // The original method: console.log(example.greet()); // "Hello World" // The aliases to that method: console.log(example.hello()); // "Hello World" console.log(example.welcome()); // "Hello World" console.log(example.hello === example.greet); // true
Legacy Decorators Compatibility
This decorator is designed to be used with the latest iteration of the
TC39 Decorators Proposal. There are, however, future plans to add a
compatibility layer for the Legacy Decorators format. This will improve
compatibility for many users whose projects still rely on the
experimentalDecorators
compiler flag, such as those using NestJS for its
Parameter Decorators (which are not included in the Stage 3 proposal).
Example 1
Example 1
import { alias } from "@decorators/alias"; class Example { // declaring our two aliases ahead of time to make typescript happy declare foo: this["bar"]; declare baz: this["bar"];
Add Package
deno add jsr:@decorators/alias
Import symbol
import * as alias from "@decorators/alias";
Import directly with a jsr specifier
import * as alias from "jsr:@decorators/alias";
Add Package
pnpm i jsr:@decorators/alias
pnpm dlx jsr add @decorators/alias
Import symbol
import * as alias from "@decorators/alias";
Add Package
yarn add jsr:@decorators/alias
yarn dlx jsr add @decorators/alias
Import symbol
import * as alias from "@decorators/alias";
Add Package
npx jsr add @decorators/alias
Import symbol
import * as alias from "@decorators/alias";
Add Package
bunx jsr add @decorators/alias
Import symbol
import * as alias from "@decorators/alias";