Custom typeguard “as narrowed” #50734
Labels
Awaiting More Feedback
This means we'd like to hear from more people who would be helped by this feature
Suggestion
An idea for TypeScript
Suggestion
🔍 Search Terms
typeguard
narrow
infer
implicit
✅ Viability Checklist
My suggestion meets these guidelines:
⭐ Suggestion
Some method for writing a typeguard that narrows based on Typescript’s regular type-narrowing rules, without having to specify the result of that narrowing. Syntax might be
as narrowed
, as in(x) => x is as narrowed
. Sinceas
is already a reserved TS keyword that must follow an expression, and cannot followis
, there is no possibility of this syntax being confused for any other valid TS expression. Andx is
is the already-implemented syntax for typeguards, keeping things consistent.The goal with this syntax would be to write
if (typeguard(x))
and have it behave exactly as if I had copied the body oftypeguard
into theif
and replaced its arguments withx
.📃 Motivating Example
💻 Use Cases
The motivation is, currently we can write:
But if we want to make
typeof x === 'object' && typeof x.foo === 'object' && typeof x.foo.bar === 'object' && x.foo.bar.baz !== undefined
re-usable, we have to define a custom typeguard:In addition to being verbose, this isn’t precisely typesafe—if the typeguard returns
true
, Typescript just assumes thatx
has this type, it doesn’t actually check that our typeguard has ensured that (beyond basic assignability checks to ensure that it is possible thatx
might have this type). In other words, it is my responsibility to ensure thatif (isFooBarBaz(x))
is equivalent to the narrowing that Typescript does for me when I writeif (typeof x === 'object' && typeof x.foo === 'object' && typeof x.foo.bar === 'object' && x.foo.bar.baz !== undefined)
.The problem with that is, if I update the definition of
Foo
to allow the possiblebaz
property to have the typestring | number
, but forget to updateisFooBarBaz
, Typescript will accept the assertion thatbaz
is anumber
even though I only checked it was!== undefined
, and it could be astring
. I want a typeguard where the compiler would catch this, just as it does for the non-typeguard version.Thus the proposal:
By using
x is as narrowed
, myif(isFooBarBaz(x))
is actually identical to the originalif (typeof x === 'object' && typeof x.foo === 'object' && typeof x.foo.bar === 'object' && x.foo.bar.baz !== undefined)
, and Typescript is handling its type in exactly the same way. I don’t have to determine (and maintain) the type signature ofisFooBarBaz
.The text was updated successfully, but these errors were encountered: