ezolenko / rollup-plugin-typescript2

Rollup plugin for typescript with compiler errors.
MIT License
817 stars 71 forks source link

Add schema checking for plugin options #312

Open agilgur5 opened 2 years ago

agilgur5 commented 2 years ago

What kind of feature would you like and why?

This is a feature request, not a bug -- need to make a different issue template for that.

Schema checking for plugin options would improve the DX of this plugin by catching some common user errors / misconfigurations early on. For instance, #236 and #229 (and partly #62) are both due to trying to place compilerOptions directly into this plugin's options, and not in tsconfigOverrides.compilerOptions. #159 and #157 are also similar in that they were missing compilerOptions (and the answer in https://github.com/ezolenko/rollup-plugin-typescript2/issues/157#issuecomment-504545505 has 12+ upvotes, so seems to be a general point of confusion, possibly due to configuration differences b/t rpt and rpt2). Most of the issues labeled solution: invalid are due to these "invalid" misconfigurations (may want to make a more specific label for that though...)

This kind of validation would also hopefully help reduce the amount of erroneous bug reports due to misconfigurations that this plugin receives.

Implementation Details

A simple, naive, first-pass implementation of this could be to just check if all first-level keys passed into this plugin's options are valid options.

More in-depth implementations can check a full schema and deeper levels, but I think the first-pass would actually handle 80%+ of these kinds of issues

Versions

  npmPackages:
    rollup: ^2.70.1 => 2.70.1 
    rollup-plugin-typescript2: ^0.31.2 => 0.31.2 
    typescript: ^4.4.0 => 4.6.3 
agilgur5 commented 2 years ago

So I looked through the rollup/plugins repo (including things like validation source code) to see if there was an official / standard way of doing schema validation in plugins, but it turns out the answer is no: https://github.com/rollup/plugins/issues/154 πŸ˜•

Several libraries were mentioned there, but none chosen, and the issue was closed as stale eventually. There was also discussion of using TS interfaces as schemas, but notably, ts-interface-checker wasn't mentioned there, which does just that but with an extra step of generating runtime code. Decorator techniques (I assume a la emitDecoratorMetadata) were briefly mentioned as well.

Previous Art and references in the interface space: Babel, with reference to Angular: https://github.com/babel/babel/issues/5201#issuecomment-292689538 Old TS issue for run-time type-checking: https://github.com/microsoft/TypeScript/issues/1573 AtScript is mentioned in both: https://github.com/angular/atscript-playground (surprisingly, I actually hadn't heard of this one before!) tcomb mentioned of course: https://github.com/gcanti/tcomb Which is one of the inspirations for MobX-State-Tree (MST): https://github.com/mobxjs/mobx-state-tree

MST is great (also has made some of my IDEs really chug on the types πŸ˜… ) and not deprecated, but afaik, there's no way to decouple the schema/models from the state tree portion of it for use in pure schema validation; I'd probably already have used it by now otherwise... πŸ˜•

MST and other previous art (React prop-types too) also show that the opposite may be better (esp. with regard to type narrowing), i.e. inferring an interface from the run-time schema.

agilgur5 commented 1 year ago

Recently found https://github.com/moltar/typescript-runtime-type-benchmarks and figured I'd notate some more here.

While the benchmarks themselves aren't super relevant for our use-case given that they'd only run once per build, the repo also contains a long list of different TS runtime type-checking tools. Among them, I particularly liked ok-computer, simple-runtypes, and valita.

But tbh, the most popular of the lot is still superstruct, which seemed to have been the preferred choice in https://github.com/rollup/plugins/issues/154 before it was auto-closed as stale. Not that popularity means that much, but given that we have a fairly simple use-case / need, using the most well-supported one may be optimal for longevity.

There was also discussion of using TS interfaces as schemas, but notably, ts-interface-checker wasn't mentioned there, which does just that but with an extra step of generating runtime code.

ts-interface-checker is listed in the benchmark. I also saw typescript-json floating around recently (blew up a bit in popularity, but is very new), which uses TS interfaces along with a custom TS transformer to generate runtime types. ts-runtime-checks, from the benchmark, uses a similar approach as well. spectypes is somewhat similar in that it uses a Babel plugin to generate runtime checks, but it doesn't use TS interfaces.

MST and other previous art (React prop-types too) also show that the opposite may be better (esp. with regard to type narrowing), i.e. inferring an interface from the run-time schema.

In any case, most schema / runtime type-checking libraries nowadays can derive / infer a TS interface from the schema, so you still only need to define the schema once.

Adding a TS transformer to our own build pipeline adds a new complexity (though it would be dogfooding more), so I think I'm more for just adding a run-time schema like superstruct and just running with it until there's some standardization or choices upstream in the Rollup community etc.