TypeScript Interfaces Do Not Provide Type Safety
TypeScript interfaces are a way to define the shape of an object and they’re pretty commonly used through-out any real-world projects and production applications. However, they may also give a false sense of security when types are more structured and complex in this way - a formal interface.
TypeScript Interfaces Are Not Enforced at Runtime
TypeScript expects to uphold the following generic interface which you may recognize from the Express.js library for handling HTTP requests:
(alias) interface Request<P = core.ParamsDictionary, ResBody = any, ReqBody = any, ReqQuery = qs.ParsedQs, Locals extends Record<string, any> = Record<string, any>> import Request
Let’s say you’re building on-top of this HTTP function handler interface, as follows:
interface UserComponentQueryString { name?: string;}
class UserController {
public getUserHelloComponent: RequestHandler = async ( _req: Request<{}, {}, {}, UserComponentQueryString>, res: Response) => {
const userName = _req.query.name || "World";
const helloComponent = `<h1>Hello, ${userName}!</h1>`; return res.send(helloComponent); }}
What happens if the name
query parameter is not a string? What if it’s an array of strings or an object? TypeScript interfaces do not provide type safety at runtime, so the following request will still be evaluated as-is by the Express route handler:
$ curl -G -X 'GET' -H 'accept: application/json' "http://localhost:8080/users/component" --data-urlencode "name[]=<img src=x onError=alert(1) />"
<h1>Hello, <img src=x onError=alert(1) />!</h1>