{"id":12252,"library":"typescript-rest","title":"TypeScript REST API Library","description":"typescript-rest is a lightweight, annotation-based library designed to simplify the creation of RESTful APIs with TypeScript and Express.js. It leverages decorators to define API endpoints, parameters, and HTTP methods, allowing developers to structure their API services cleanly within TypeScript classes. The library is currently stable at version 3.0.4, with recent minor updates indicating active maintenance. Key differentiators include its tight integration with Express, built-in support for dependency injection via IoC containers like `typescript-ioc` (with a dedicated factory module), and its focus on a declarative API definition style using standard TypeScript decorators. This approach aims to reduce boilerplate and improve type safety for Node.js backend development, providing a structured way to build scalable backend services.","status":"active","version":"3.0.4","language":"javascript","source_language":"en","source_url":"https://github.com/thiagobustamante/typescript-rest","tags":["javascript","API","REST","RESTFul","service","microservice","typescript","node server"],"install":[{"cmd":"npm install typescript-rest","lang":"bash","label":"npm"},{"cmd":"yarn add typescript-rest","lang":"bash","label":"yarn"},{"cmd":"pnpm add typescript-rest","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core web server framework extended by typescript-rest. Required at runtime.","package":"express","optional":false},{"reason":"Required for compiling TypeScript code, especially for decorator support. Development dependency.","package":"typescript","optional":false},{"reason":"Required when `emitDecoratorMetadata` is enabled in `tsconfig.json` for decorator metadata reflection. Required at runtime.","package":"reflect-metadata","optional":false},{"reason":"Optional peer dependency for using `typescript-ioc` as an Inversion of Control container for dependency injection.","package":"typescript-ioc","optional":true},{"reason":"Optional peer dependency; provides the service factory to integrate `typescript-rest` with `typescript-ioc`.","package":"typescript-rest-ioc","optional":true}],"imports":[{"note":"The primary entry point for registering decorated service classes with an Express application. It is a named export, not a default export.","wrong":"import Server from 'typescript-rest';","symbol":"Server","correct":"import { Server } from 'typescript-rest';"},{"note":"Decorators like `Path`, `GET`, `POST`, `PathParam`, etc., are named exports. Ensure TypeScript compiler options `experimentalDecorators` and `emitDecoratorMetadata` are set to `true`.","wrong":"const Path = require('typescript-rest').Path;","symbol":"Path","correct":"import { Path, GET, PathParam } from 'typescript-rest';"},{"note":"While `import express from 'express';` often works with `esModuleInterop: true`, `import * as express from 'express';` is a more robust import style for the Express module in TypeScript projects to correctly handle its CommonJS export structure.","wrong":"import express from 'express';","symbol":"express.Application","correct":"import * as express from 'express';"}],"quickstart":{"code":"import * as express from \"express\";\nimport { Server, Path, GET, PathParam } from \"typescript-rest\";\n\n// Ensure you have 'npm install reflect-metadata' and import it once globally if using IoC/complex types with decorators:\n// import 'reflect-metadata'; \n\n@Path(\"/hello\")\nclass HelloService {\n  @Path(\":name\")\n  @GET\n  sayHello( @PathParam('name') name: string ): string {\n    return \"Hello \" + name;\n  }\n}\n\nlet app: express.Application = express();\n\n// Build and register all decorated services with the Express app\nServer.buildServices(app);\n\napp.listen(3000, function() {\n  console.log('typescript-rest server listening on port 3000!');\n  console.log('Try: GET http://localhost:3000/hello/john_doe');\n});\n","lang":"typescript","description":"Demonstrates defining a simple REST endpoint using decorators (`@Path`, `@GET`, `@PathParam`) and integrating it with an Express application."},"warnings":[{"fix":"Review the project's GitHub releases and Wiki for detailed migration instructions and API changes between major versions.","message":"Upgrading from `typescript-rest` v2.x to v3.x may introduce breaking changes. Always consult the official changelog or migration guide before a major version upgrade to understand specific API changes.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Add `\"experimentalDecorators\": true, \"emitDecoratorMetadata\": true` to your `compilerOptions` in `tsconfig.json`. Install `reflect-metadata` (`npm install reflect-metadata`) and import it once at your application's entry point (`import 'reflect-metadata';`).","message":"TypeScript's experimental decorators (`experimentalDecorators: true` in tsconfig.json) are required for `typescript-rest` to function. Additionally, `emitDecoratorMetadata: true` and `reflect-metadata` (imported once globally) are essential for advanced features like dependency injection and proper type reflection.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Ensure your `tsconfig.json` explicitly enables `experimentalDecorators: true`. If targeting Node.js, `\"target\": \"es6\"` or newer is recommended. Be aware that the `experimentalDecorators` flag will eventually be deprecated by TypeScript, potentially requiring future migration.","message":"TypeScript 5.0 introduced a new, standardized decorators implementation. `typescript-rest` currently relies on TypeScript's 'legacy' or 'experimental' decorators. Mixing these with native TS 5+ decorators or failing to configure `tsconfig.json` correctly for legacy decorators can lead to unexpected behavior or compilation errors.","severity":"gotcha","affected_versions":">=5.0.0 of TypeScript"},{"fix":"Implement custom error handling middleware in Express, ensuring it's defined and registered after `Server.buildServices(app)` in your application setup. Example: `app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => { /* handle error */ });`","message":"Error handling in `typescript-rest` relies on Express.js middleware. Custom error handling middleware should be registered *after* `Server.buildServices(app)` to catch errors thrown by the REST services. Incorrect ordering can result in unhandled exceptions or generic 500 responses.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Install `reflect-metadata` (`npm install reflect-metadata`) and add `import 'reflect-metadata';` once at the very top of your application's entry file (e.g., `server.ts` or `app.ts`).","cause":"The `reflect-metadata` polyfill was not loaded, which is required by TypeScript's `emitDecoratorMetadata` feature.","error":"ReferenceError: Reflect is not defined"},{"fix":"In your `tsconfig.json`, add `\"experimentalDecorators\": true` to the `compilerOptions` section.","cause":"The TypeScript compiler option `experimentalDecorators` is not enabled, preventing the use of decorator syntax.","error":"Decorator '...' is not a valid decorator factory."},{"fix":"Ensure that your API methods and middleware handle responses exactly once. For asynchronous operations, ensure you `await` promises. If using custom error handlers, make sure they only attempt to send a response if one hasn't already been sent, or pass control to the next error handler using `next(err)`.","cause":"This is a common Express.js error, often occurring when an asynchronous operation or error handler attempts to send a response after one has already been sent (e.g., by a decorator, another middleware, or a prior `res.send`/`res.json` call).","error":"Error: Can't set headers after they are sent to the client."},{"fix":"Make the parameter type explicit to allow `undefined` or provide a default value. For example, change `id: string` to `id?: string` or `id: string = 'default_value'`.","cause":"This TypeScript error often occurs when a decorated parameter (e.g., `@QueryParam('id') id: string`) might implicitly be `undefined` or `null` if the client doesn't provide it, but the method parameter expects a non-nullable type.","error":"Argument of type 'string | undefined' is not assignable to parameter of type 'string'."}],"ecosystem":"npm"}