Zum Hauptinhalt springen
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
Windows Tipps & SecurityGrafikkarte vor Überhitzung schützen: So geht’s(25.09.2026 um 08:00 Uhr)
••••••••••
Windows Tipps & SecurityGrafikkarte vor Überhitzung schützen: So geht’s(25.09.2026 um 08:00 Uhr)
••••••••••
Intelligence View
⚡ tsecurity.de Intelligence

Leveraging the TS type system with APIs: Validation, error handling and free OpenAPI specs

How many times have you been frustrated by out of date or incomplete API documentation? How many times have you realised that you were responsible for the out of date information?! Building and maintaining API documentation that is an…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

How many times have you been frustrated by out of date or incomplete API documentation? How many times have you realised that you were responsible for the out of date information?!

Building and maintaining API documentation that is an up-to-date reflection of the API itself can be a chore. Input validation and error handling can be hard to maintain, tricky to test, prone to inconsistencies, and easy to overlook. I'm going to explore how we can leverage the TypeScript type system to make these problems less of an issue, whilst generating API specifications for free! 💸





Common API issues





Inaccurate documentation



One thing worse than missing API documentation is out-of-date API documentation. If the documentation is written in a separate location to the API code then it becomes very manual to keep both in sync with each other. Even if as a developer making a change you remember to update the documentation, you could still introduce a subtle mistake. A common user mistake I've experienced for example is forgetting to nest a response value with a { data: {} } wrapper or similar.





Overlooking input validation



Then there's maintaining input validation - what if your API is expecting a UUID as an input but you're accidentally sending an auto-incrementing number, or post slug? What if your application just expects the input payload to be correct and complete, but it's missing required fields? You usually have to build a validation layer, so the API will respond to any incoming user request, then the validation layer will check if all the data is present and correct before continuing to handle the request.



In some codebases I've seen these validation checks repeated in multiple, subtly different ways - because it's more boiler plate for devs to manage and maintain, and it's often easy to introduce individual validation rules for each specific endpoint. This increases cognitive load for devs too as they have to handle the cases where the input is invalid, on-top of all other edge cases.





Inconsistent error handling



Then there's error handling - is there an issue with an invalid input? Or maybe the input is fine, but we've forgotten to authenticate the request? Perhaps the entity that was requested doesn't exist, or there's a foreign key constraint in the database, or an incorrect value selected for an enum, an input string that's too long - or another internal API call that isn't responding as we expect - there's a myriad of runtime errors that we need to think about handling and testing. If we want to test at the controller level, that typically means mocking or stubbing the request and response objects so we can monitor the behaviour.





Our Solution: TSOA



(Pronounced so·uh) is a Typescript library that generates OpenAPI compliant APIs and specs (OpenAPI specification is a language-agnostic definition format used to describe RESTful APIs), that can be added to your Express, Hapi, Koa or other NodeJS frameworks. It leverages the type system, meaning requests and responses are just represented as types. Extra details are added with annotations, e.g. @Route('/api/entities') or @Get('{entityId}). It removes the boiler plate for input validation and response or error handling, which also makes testing simpler. It can also generate API specs for us, meaning the docs are an up-to-date and accurately represent our API.





Example API definition



Lets say I have an API route that expects an entity id in the path. The entity should be in the format of a UUID. I can define this like so:




import { Controller, Get, Path, Route } from 'tsoa';

/**
* Stringified UUIDv4.
* See [RFC 4112](https://tools.ietf.org/html/rfc4122)
* @pattern [0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}
* @example "52907745-7672-470e-a803-a2f8feb52944"
*/

export type UUID = string;

export class EntityController extends Controller {
/**
* Retrieves an entity by its ID.
*/

@Route('/entities/{entityId}')
@Get()
public async getEntity(
@Path() entityId: UUID
): Promise<Entity> {
// ... your logic to fetch the entity
return this.entityService.getEntity(entityId);
}
}






Notice how our function getEntity doesn't take a Request/Response/Next parameter like a typical Express callback? We're just using plain old fashioned Typescript Types, e.g return Promise<Entity> - this not only cleans up our code and is less to think about, it's also simpler to test.






Testing



Speaking of testing, let's look at a simple example of how we can test the getEntity method and its error handling using a testing framework like Jest:




describe('EntityController', () => {
let mockEntityService: any;
let controller: EntityController;
const entityId = '52907745-7672-470e-a803-a2f8feb52944';

beforeEach(() => {
mockEntityService = {
getEntity: jest.fn(),
};
controller = new EntityController(mockEntityService);
});

it('should return an entity if found', async () => {
const mockEntity = { id: entityId, name: 'Test Entity', createdAt: new Date() };
mockEntityService.getEntity.mockResolvedValue(mockEntity);

const result = await controller.getEntity(entityId);
expect(result).toEqual(mockEntity);
expect(mockEntityService.getEntity).toHaveBeenCalledWith(entityId);
});

it('should throw HTTPError with 404 status if entity is not found', async () => {
mockEntityService.getEntity.mockResolvedValue(null);

await expect(controller.getEntity(entityId)).rejects.toBeInstanceOf(HTTPError);
await expect(controller.getEntity(entityId)).rejects.toHaveProperty('status', 404);
await expect(controller.getEntity(entityId)).rejects.toHaveProperty('message', 'Entity not found');
expect(mockEntityService.getEntity).toHaveBeenCalledWith(entityId);
});
});






In this test suite, notice how we are interacting directly with the controller's method and its TypeScript type signature. We are not setting up or manipulating mock req or res objects, making our tests more focused and easier to understand.






Error handling



The TSOA library is now going to make sure that any input (in the path, params, body or headers) matches what we've defined under our @Route annotation. But other errors can occur - for example, we might ask the entity service for an entity that doesn't exist! It'd be nice if, instead of exploding with a 500 unknown error, we could return a 404 not found with a helpful error message. I created a HttpError class to make managing these errors easier




export class HTTPError extends Error {
constructor(message: string, public readonly status: number) {
super(message);
}
}






And here's a slightly simplified version of my error handler




export const errorHandler = (err: any, req: Request, res: Response, next: NextFunction) => {
if (err instanceof ValidateError) {
const body: ErrorResponse = {
errors: {
detail: {
message: err.message,
fields: err.fields,
},
},
};
res.status(422).json(body);
next();
return;
}
if (err instanceof HTTPError) {
const body: ErrorResponse = {
errors: {
detail: err.message,
},
};
res.status(err.status).json(body);
next();
return;
}

const status = err.status || 500;
const body: ErrorResponse = {
errors: {
detail: err.message || 'Internal Server Error',
},
};

res.status(status).json(body);
next();
};









Authentication & Middleware



You can require authentication for certain routes by using the @Security('name', ['scopes']) decorator, where the name is preconfigured in a typescript module - much like any Express middleware. And you can add custom middleware to controllers or routes in much the same way, by using the @Middlewares decorator. One drawback here is the engineer has to remember to add those decorators!






Up-to-date generated API specs



And finally, because TSOA leverages your TypeScript types and decorators, it can automatically generate an OpenAPI-compliant specification (usually in JSON or YAML format) of your API. This generated specification can then be used by various tools and platforms, such as Swagger UI, code generation tools, and API gateways, ensuring your documentation is always up-to-date and accurate.



Example OpenAPI using SwaggerUI






Drawbacks



It does introduce another dependency and another layer of abstraction in your application, and there may inevitably be a small performance overhead, but it may be less than you manually handling input validation and error handling anyway. I think it outweighs the drawbacks, but if performance is the most critical choice, you probably aren't using a NodeJS/Express service anyway!



If you are looking to do more advanced input validation, beyond pattern matching on strings, or some validation that can't be defined statically, e.g. authorisation - if a user can access an entity by ID - then you will still have to perform these checks in your code.






Alternatives



Zod seems to be the go-to validation library, and is very useful in some contexts, for example if you need to do more complex or nested runtime validation. But this won't generate API docs or give you error handlers or API controllers.



I noticed the NestJS framework has a module for generating docs from types and annotations, see their docs for a worked example.



OpenApi3-ts is a TS library that helps you build OpenAPI specs, but it doesn't do error handling, validation or replace your controllers!



tRPC can be a good option for creating type-safe APIs, which borrows concepts from REST and GraphQL. But this adds different tRPC boiler plate and ways-of-doing-things, which might be great for a backend/frontend monorepo situation for example, but might be harder to create a public facing API.






Conclusion



TSOA is pretty simple to introduce to an existing NodeJS/Express app, and will give you input validation generated API documentation out-the-box. Give it a try and share your feedback, on this or other approaches that have worked (or not!) for you.

1. Sofort-Triage & Abwehrmaßnahmen

SOC Incident Playbook: Vulnerability Remediation & Verification
Syntax validiert (0 Fehler)
title: Detect Exploitation - Leveraging the TS type system with APIs: Validation, error handling and free OpenAPI specs
id: 78df4408-0589-4b43-9343-83ee657d12c5
status: experimental
description: Automatisch generierte SIEM-Erkennungsregel basierend auf CTI Intelligence
references:
  - https://tsecurity.de/
author: iShareStuff CTI Automated Detection Engine
date: 2026-09-27
logsource:
  category: network_connection
  product: any
detection:
  selection:
      CommandLine|contains:
        - 'exploit'
  condition: selection
falsepositives:
  - Legitime administrative Zugriffe oder Penetrationstests
level: high
tags:
  - attack.initial_access
Syntax validiert (0 Fehler)
rule CTI_Threat_Indicator {
    meta:
        author = "iShareStuff CTI Automated Detection Engine"
        date = "2026-09-27"
        description = "YARA Signature for "
    strings:
        $str = "Leveraging the TS type system " ascii wide
    condition:
        any of them
}
Syntax validiert (0 Fehler)
index=security sourcetype IN ("cisco:asa", "pan:traffic", "zeek_conn", "suricata", "WinEventLog:Security")
("Leveraging the TS type system with APIs ")
| stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip, dest_ip, dest_host, signature
| eval first_seen=strftime(first_seen, "%Y-%m-%d %H:%M:%S"), last_seen=strftime(last_seen, "%Y-%m-%d %H:%M:%S")
| sort - count
Syntax validiert (0 Fehler)
message: "*Leveraging the TS type system with APIs *"
Syntax validiert (0 Fehler)
CommonSecurityLog
| where Message has "Leveraging the TS type system with APIs "
| summarize EventCount = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by SourceIP, DestinationIP, DestinationPort, Activity
| extend DetectionRule = "iShareStuff-CTI-Compiled"
| sort by EventCount desc

2. Cyber Threat Intelligence & Forensik

CTI Threat Relationship Graph2 Knoten / 1 Relationen
CVE / Incident Software MITRE ATT&CK CWE Weakness IoC
🎯
MITRE ATT&CK Matrix Navigator 14 Taktiken
Reconnaissance
-
Resource Development
-
Initial Access
Execution
Persistence
-
Privilege Escalation
Defense Evasion
Credential Access
-
Discovery
-
Lateral Movement
-
Collection
-
Command and Control
Exfiltration
-
Impact
tsecurity.de Cognitive Threat RAG
Fokus-Vektor:

Analyse für identifizierte Bedrohung auf Basis von Live-CTI (ENISA EUVD): CVSS 0.0 · EPSS 0.0% · CISA KEV: nein. Handlungsableitung aus den verlinkten Hersteller-Quellen.

🛡️ Angriffsfläche & Exposure

Netzwerk/Remote-Zugriff ohne Vorauthentifizierung möglich.

⚡ Empfohlene Sofortmaßnahmen
  • 1. Perimeter-Inspektion: Relevante Portfreigaben und exponierte Endpunkte unverzüglich scannen.
  • 2. Patch-Applikation: Hersteller-Hotfix einspielen oder betroffene Daemons in isolierte DMZ-Segmente überführen.
  • 3. Telemetrie & EDR-Alerts: Prozessaufrufe und Child-Processes auf anomale Shell-Spawns überwachen.
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Leveraging the TS type system with APIs: Validation, error handling and free OpenAPI specs

Thematisch verwandte Begriffe: Leveraging, type, system, with · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

💬 Kommentare werden geladen…
Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-100739 | A vulnerability was detected in mathurvishal CloudClassroom-PHP-Project…
Advisory →
tsecurity.de Icon
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag