Enforcing types on untyped data in TypeScript

2020-07-18 06:04发布

问题:

I'm wondering if there are any tools or techniques that are being used to do low level validation on object data when using TypeScript. An example would be a JSON body of a POST request on a HTTP service. Typically I've created an interface for the expected data and then cast the data to that interface but I'm aware that this is superficial.

Example:

router.route('/supercres')
    .get((req, res, next) => {
        const typedBody = <SuperCresBody>req.body;
    })

interface SuperCresBody {
    name: string,
    yoyo: boolean,
}

The problem with enforcing the interface is that TypeScript is just a compile-time concept and does not enforce anything at runtime. Knowing this I'm curious if anybody has found a clever way without a lot of boilerplate or tooling in order to pull off type checking at runtime for these things without having to repeat the interface contract as a set of imperative checks as a validation step.

On a somewhat related note, in the most recent episode of Functional Geekery, Matthias Felleisen explains a similar need in Typed Racket near the tail end of the episode.

Related Reading:

  • COMBINING STATIC AND RUNTIME TYPE CHECKING FOR BETTER DEV PRODUCTIVITY

回答1:

Check these 2 equivalent projects:

  • https://github.com/gcanti/io-ts
  • https://github.com/pelotom/runtypes

I use the latest, it works flawlessly, but the former looks awesome as well.

In both cases, you build a validator that you use to:

  • Check object at runtime
  • Extract a static type that can be used at compile time

In your specific (api) use case, you can also use some tooling to extract TS types form the JSON or XML you produce

You can also generate typings easily from JSON data:

http://json2ts.com/