TypeScript REST API Library
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.
Common errors
-
ReferenceError: Reflect is not defined
cause The `reflect-metadata` polyfill was not loaded, which is required by TypeScript's `emitDecoratorMetadata` feature.fixInstall `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`). -
Decorator '...' is not a valid decorator factory.
cause The TypeScript compiler option `experimentalDecorators` is not enabled, preventing the use of decorator syntax.fixIn your `tsconfig.json`, add `"experimentalDecorators": true` to the `compilerOptions` section. -
Error: Can't set headers after they are sent to the client.
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).fixEnsure 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)`. -
Argument of type 'string | undefined' is not assignable to parameter of type 'string'.
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.fixMake 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'`.
Warnings
- breaking 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.
- gotcha 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.
- gotcha 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.
- gotcha 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.
Install
-
npm install typescript-rest -
yarn add typescript-rest -
pnpm add typescript-rest
Imports
- Server
import Server from 'typescript-rest';
import { Server } from 'typescript-rest'; - Path
const Path = require('typescript-rest').Path;import { Path, GET, PathParam } from 'typescript-rest'; - express.Application
import express from 'express';
import * as express from 'express';
Quickstart
import * as express from "express";
import { Server, Path, GET, PathParam } from "typescript-rest";
// Ensure you have 'npm install reflect-metadata' and import it once globally if using IoC/complex types with decorators:
// import 'reflect-metadata';
@Path("/hello")
class HelloService {
@Path(":name")
@GET
sayHello( @PathParam('name') name: string ): string {
return "Hello " + name;
}
}
let app: express.Application = express();
// Build and register all decorated services with the Express app
Server.buildServices(app);
app.listen(3000, function() {
console.log('typescript-rest server listening on port 3000!');
console.log('Try: GET http://localhost:3000/hello/john_doe');
});