Skip to content

Types Are Enforced at Development Only

A common misconception is that TypeScript provides fault-proof types safety. However, many developers have a deep TypeScript security fallacy in this regard and they do not realize that TypeScript is limited only to development-time type checking. TypeScript types are not enforced at runtime and are stripped away during the compilation process. This compilation process is what turns the rich TypeScript language into its bare-bones JavaScript detail.

TypeScript Types are Stripped Away in Runtime

In the following example we do not use any type and instead we’re enforcing the string type for the filterQuery variable. This is a good practice as it allows TypeScript to enforce type checking at development-time:

class UserController {
public getUsers: RequestHandler = async (_req: Request, res: Response) => {
// we now define query as string
const filterQuery: string = _req.query.filter as string || '';
const serviceResponse = await userService.findAll({ filter: filterQuery });
return handleServiceResponse(serviceResponse, res);
};

If you compile the code with tsc you’ll see we get no errors or warnings here:

Terminal window
$ npx tsc

What happens if the filter query string that gets passed to this request handler function as the filterQuery variable is specified by the user to be used as an array?

The user can launch an HTTP GET request with the [] bracket notation which often is interpeted by HTTP web frameworks like Express on a running Node.js server, that the query string is actually an array and it will indeed be interpreted this way: filter = ['Al'] in the query string example below:

Terminal window
$ curl -X 'GET' -H 'accept: application/json' "http://localhost:8080/users?filter[]=Al"
{
"success": true,
"message": "Users found",
"responseObject": [
{
"id": 1,
"name": "Alice",
"email": "alice@example.com",
"age": 42,
"createdAt": "2025-01-13T10:51:37.118Z",
"updatedAt": "2025-01-18T10:51:37.118Z"
}
],
"statusCode": 200
}

As you can see, there are no runtime exception or errors thrown even though the filter query string received a string. The functionality still works because the .toString() implementation for an Array is to return the first element at position 0.