-
Notifications
You must be signed in to change notification settings - Fork 13k
Description
π Search Terms
runtime type guards, typescript reflection, code generation, type validation
β Viability Checklist
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
- This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
β Suggestion
This idea was bounced a couple of times already, but wondering if it would still be out of scope today.
#15265, #3628, #49610
I realize it would be a rather big maintenance burden to add to the compiler, but year after year I come across this problem and end up using external libraries. I maintained ts-auto-guard for a while and it had to rely on intricate compiler internals. Since the go-rewrite especially, I havenβt seen a library that works really well.
I am wondering if it makes more sense to expose a stable reflection API or to have guard functionality embedded here. Personally I lean toward the latter for the reasons below.
Issues that come with it from the top of my head:
Types can be very complex
That was also my problem in ts-auto-guard. But in practice, types that need to be de/serialized are usually simple. Unsupported types or constructs would immediately fail at compile time, so there is no hidden complexity for the user. This is the reason I vote for type guards generation directly here, as opposed to a stable reflect API and a generator library based on it.
Requires a lot of maintenance time
Understandable, but the alternative is projects depending on fragile libraries that re-implement the same logic against private compiler APIs. A single stable implementation in the compiler seems cheaper long-term. Long live MS shareholders!
π Motivating Example
// Data coming from untyped source
const input = JSON.parse(await fetch("/api/user").then(r => r.text()));
type User = {
id: number;
name: string;
email?: string;
}
// everything below is deriveable at compile-time
function isUser(x: any): x is User {
return typeof x?.id === "number"
&& typeof x?.name === "string"
&& (x.email === undefined || typeof x.email === "string");
}
if (!isUser(input)) throw new Error("Invalid user");
π» Use Cases
Nothing specific - the earlier we are warned about type errors the better. Raison d'etre of TS :)