Skip to content

Proposal: Reevaluate compiler-generated runtime type guards.Β #62470

@0xorial

Description

@0xorial

πŸ” Search Terms

runtime type guards, typescript reflection, code generation, type validation

βœ… Viability Checklist

⭐ 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 :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Out of ScopeThis idea sits outside of the TypeScript language design constraintsSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions