{"id":19806491,"url":"https://github.com/monade/typescript-decorators","last_synced_at":"2025-11-11T19:29:54.564Z","repository":{"id":239596393,"uuid":"797952549","full_name":"monade/typescript-decorators","owner":"monade","description":null,"archived":false,"fork":false,"pushed_at":"2024-05-16T09:56:25.000Z","size":27,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-25T13:04:14.773Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/monade.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-05-08T19:52:02.000Z","updated_at":"2025-01-31T07:34:51.000Z","dependencies_parsed_at":"2024-05-16T10:53:56.574Z","dependency_job_id":null,"html_url":"https://github.com/monade/typescript-decorators","commit_stats":null,"previous_names":["monade/typescript-decorators"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/monade/typescript-decorators","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monade%2Ftypescript-decorators","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monade%2Ftypescript-decorators/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monade%2Ftypescript-decorators/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monade%2Ftypescript-decorators/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/monade","download_url":"https://codeload.github.com/monade/typescript-decorators/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monade%2Ftypescript-decorators/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260852155,"owners_count":23072604,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T09:07:42.198Z","updated_at":"2025-11-11T19:29:54.526Z","avatar_url":"https://github.com/monade.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Typescript Decorators\n\nThis repository contains examples of Typescript decorators.\n\n## Introduction\n\nTypescript decorators are a way to add metadata to classes, methods, properties, or parameters. They are a feature of the language that allows you to write code that modifies the behavior of a class or method. Decorators are a way to add functionality to a class or method without changing the class or method itself.\n\n## How to write a decorator\n\nA typescript is essentially a function that takes a target object and a few metadata.\n\n```typescript\nfunction myDecorator(target: any, /* other info */) {\n    /* do stuff */\n}\n\n@myDecorator\n/* the class, property or method */\n```\n\nExample:\n    \n```typescript\nfunction myDecorator\u003cT extends Object\u003e(target: T) {\n    console.log(`Decorating ${target.constructor.name}`);\n}\n\n@myDecorator\nclass MyClass {\n    /* ... */\n}\n\n// Output: Decorating MyClass\n```\n\nYou can apply multiple decorators to the same class, property, or method.\n\n```typescript\n@decorator1\n@decorator2\n@decorator3\n/* the class, property or method */\n```\n\n## Decorator Factories\n\nA decorator factory is a way to pass parameters to a decorator.\nIt's a function that returns a decorator (another function).\n\n```typescript\nfunction myDecoratorFactory(/* decorator parameters */) {\n    return function myDecorator(target: any, /* other info */) {\n        /* do stuff */\n    };\n}\n```\n\nUsage:\n\n```typescript\n@myDecoratorFactory(/* decorator parameters */)\n/* the class, property or method */\n```\n\n## Decorator Metadata\nOne of the primary use cases for decorators is to add metadata to a class, method, property, or parameter. This metadata can be used by other parts of the code to determine how to interact with the decorated element.\n\nTypescript provides a way to access this metadata using the `Reflect` object. The `Reflect` object is available through a polyfill using the library `reflect-metadata`.\n\n```typescript\nimport 'reflect-metadata';\n\nfunction myDecorator(target: any) {\n    Reflect.defineMetadata('myMetadata', 'myValue', target);\n}\n\n@myDecorator\nclass MyClass {\n    /* ... */\n}\n\nconst metadata = Reflect.getMetadata('myMetadata', MyClass);\n```\n\n## Types of Decorators\n\nThere are five types of decorators in Typescript:\n- Class decorators\n- Method decorators\n- Accessor decorators\n- Property decorators\n- Parameter decorators\n\n### Class decorators\n\nType Signature:\n```typescript\n/** @param {T} constructor the class constructor */\nfunction classDecorator\u003cT extends { new (...args: any[]): {} }\u003e(constructor: T): void | T {\n    /* do stuff with constructor */\n    /* ... */\n\n    /* eventually return a new constructor */\n    // return class extends constructor {\n    //     /* do stuff with the new constructor */\n    // };\n}\n```\n\nUsage:\n\n```typescript\n@classDecorator\nclass MyClass {\n    /* ... */\n}\n```\n\nExamples:\n- [Class Sealing](src/class-decorators/class-sealing.ts): A class decorator that seals a class.\n- [Class Registry](src/class-decorators/class-registry.ts): A class decorator that adds a class to a registry (a key-value map).\n- [Class Reference Count](src/class-decorators/class-reference-count.ts): A class decorator that rewrites a class constructor to keep track of the number of instances created.\n- [Class Metadata](src/class-decorators/class-metadata.ts): A class decorator that adds some metadata to a class that can be retrieved later.\n- [Class Singleton](src/class-decorators/class-singleton.ts): A class decorator that makes a class a singleton.\n- [Class Method Logging](src/class-decorators/class-method-logging.ts): A class decorator that logs every method call by wrapping them.\n\n**Caveats**\n\n- When re-writing a class (like in [Class Method Logging](src/class-decorators/class-method-logging.ts)), you need to be aware that the new class will have a different name and prototype than the original class.\n- Take care of the typing: if you extend the original class, the new methods won't be visible in the type system.\n- In the example [Class Registry](src/class-decorators/class-registry.ts), be aware that Tree-shaking may remove the class from the registry if it's not used anywhere else in the code. You may need to explicitly import the whole module in the entry file to prevent this.\n\n\n### Method decorators\nType Signature:\n\n```typescript\n/** @param {T} target the class prototype */\n/** @param {string} propertyKey the name of the method */\n/** @param {PropertyDescriptor} descriptor the method descriptor */\nfunction methodDecorator\u003cT extends Object\u003e(target: T, propertyKey: string, descriptor: PropertyDescriptor) {\n    /* do stuff with target, propertyKey, and descriptor */\n    /* ... */\n\n    /* eventyally modify the descriptor */\n    // descriptor.value = function () {\n    //     /* do stuff with the original method */\n    //     /* ... */\n    // };\n}\n```\n\nUsage:\n\n```typescript\nclass MyClass {\n    @methodDecorator\n    myMethod() {\n        /* ... */\n    }\n}\n```\n\nExamples:\n- [Method Typecheck](src/method-decorators/method-typecheck.ts): A method decorator that type-checks the arguments and return value of a method.\n- [Method Logging](src/method-decorators/method-safe.ts): A method decorator that wraps a method to catch and log errors that occur during its execution.\n- [Method Timeout](src/method-decorators/method-timeout.ts): A method decorator that introduces a timeout to an async method.\n\n### Accessor decorators\nSignature:\n\n```typescript\n/** @param {T} target the class prototype */\n/** @param {string} propertyKey the name of the accessor */\n/** @param {PropertyDescriptor} descriptor the accessor descriptor */\nfunction accessorDecorator\u003cT extends Object\u003e(target: T, propertyKey: string, descriptor: PropertyDescriptor) {\n    /* do stuff with target, propertyKey, and descriptor */\n    /* ... */\n\n    /* eventyally modify the descriptor */\n    // descriptor.get = function () {\n    //     /* do stuff with the original getter */\n    //     /* ... */\n    // };\n}\n```\n\nUsage:\n\n```typescript\nclass MyClass {\n    @accessorDecorator\n    get myProperty() {\n        /* ... */\n    }\n}\n```\n\nExamples:\n- [Accessor Cache](src/accessor-decorators/accessor-cache.ts): An accessor decorator that caches the result of a getter. It also show how to invalidate the cache.\n- [Accessor Descriptors](src/accessor-decorators/accessor-descriptors.ts): An accessor decorator that interacts with the property descriptor of a getter and changes its behavior. (i.e. making it read-only, enumerable, etc.)\n- [Accessor Logging](src/accessor-decorators/accessor-logging.ts): An accessor decorator that logs the access to a getter.\n\n### Property decorators\nSignature:\n\n```typescript\n/** @param {T} target the class prototype */\n/** @param {string} propertyKey the name of the property */\nfunction propertyDecorator\u003cT extends Object\u003e(target: T, propertyKey: string) {\n    /* do stuff with target and propertyKey */\n    /* ... */\n}\n```\n\nUsage:\n\n```typescript\nclass MyClass {\n    @propertyDecorator\n    myProperty: string;\n}\n```\n\nExamples:\n- [Property Dependency Injection](src/property-decorators/property-dependency-injection.ts): A property decorator that injects a dependency into a property.\n- [Property Metadata Typecheck](src/property-decorators/property-metadata-typecheck.ts): A property decorator that adds typing metadata to a property, then checks it using a function.\n- [Property Angular-like Input](src/property-decorators/property-input.ts): A property decorator that creates an Angular-like input property.\n\n**Pro Tip:**\n\nThe example [Property Metadata Typecheck](src/property-decorators/property-metadata-typecheck.ts) can be achieved with no code by setting the `emitDecoratorMetadata` option to `true` in the `tsconfig.json` file.\n\n```json\n{\n    \"compilerOptions\": {\n        \"emitDecoratorMetadata\": true\n    }\n}\n```\n\n**Caveats**\nIn the `Property Dependency Injection` example, may not work if you set the target to `ES2022` in the `tsconfig.json` file. You may need to set `useDefineForClassFields` to `false` to make it work.\n\n```json\n{\n    \"compilerOptions\": {\n        \"target\": \"ES2022\",\n        \"useDefineForClassFields\": false\n    }\n}\n```\n\nThis is because the `useDefineForClassFields` option changes the way class fields are defined.\n\n### Parameter decorators\nSignature:\n\n```typescript\n/** @param {T} target the class prototype */\n/** @param {string} propertyKey the name of the method */\n/** @param {number} parameterIndex the index of the parameter */\nfunction parameterDecorator\u003cT extends Object\u003e(target: T, propertyKey: string, parameterIndex: number) {\n    /* do stuff with target, propertyKey, and parameterIndex */\n    /* ... */\n}\n```\n\nUsage:\n\n```typescript\nclass MyClass {\n    myMethod(@parameterDecorator myParameter: string) {\n        /* ... */\n    }\n}\n```\n\n**Caveats**\n\nParameter decorators can't modify directly the behavior of a method. They can only be used to add metadata to a parameter.\nYou may need to use them in conjunction with other decorators to achieve the desired behavior. See the examples below.\n\nExamples:\n- [Parameter Validation](src/parameter-decorators/parameter-validation.ts): Parameter validation using parameter decorators.\n- [Parameter Dependency Injection](src/parameter-decorators/parameter-dependency-injection.ts): Shows how to achieve an angular-like dependency injection using parameter decorators in the constructor.\n- [Parameter Transformation](src/parameter-decorators/parameter-transformation.ts): Shows how to transform or sanitize parameters using parameter decorators.\n- [Parameter Can't Modify Methods](src/parameter-decorators/parameter-cant-modify-methods.ts): Shows that parameter decorators can't modify the behavior of a method directly.\n\n## Functional Javascript and Decorators\nUnfortunately Typescript decorators unfortunately don't support decorating a function directly.\n\n```typescript\nfunction myDecorator() {\n    /* ... */\n}\n\n// This won't work\n@myDecorator\nfunction myFunction() {\n\n}\n```\n\nHowever, you can achieve similar functionality by using higher-order functions.\n\n```typescript\nfunction myDecorator(fn: Function) {\n    return function (...args: any[]) {\n        /* do stuff before calling the function */\n        /* ... */\n\n        const result = fn(...args);\n\n        /* do stuff after calling the function */\n        /* ... */\n\n        return result;\n    };\n}\n\nconst myFunction = myDecorator(function () {\n    /* ... */\n});\n```\n\nExamples:\n- [Function decorator](src/function-decorators/function-decorator.ts): Shows how to achieve similar functionality to a function decorator using higher-order functions.\n- [Function fancier decorator](src/function-decorators/function-fancier-decorator.ts): Shows a pattern that helps achieving more complex functionality by introducing a `decorate` function.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmonade%2Ftypescript-decorators","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmonade%2Ftypescript-decorators","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmonade%2Ftypescript-decorators/lists"}