Repository navigation
Make type narrowing for destructured discriminated unions work for more types #59657
Description
Activity
- addedHelp WantedYou can do thisYou can do thisPossible ImprovementThe current behavior isn't wrong, but it's possible to see that it might be better in some casesThe current behavior isn't wrong, but it's possible to see that it might be better in some cases
on Aug 16, 2024 🔈 I'm working on the "alternative solution" which aims to use type predicts or assert function to narrow the type of the destructured variables.
My findings:
declare const data: Data const { ready, payload } = toRefs(data) if (isDataPrepared(data): data is DataPrepared) { ready.value // ^ narrow |ready| based on asserted |data| because it shares same symbol with argument |data| in |toRefs| }
Now I can check the initializer is
toRefs(data)while checking the identifierready. Inready's flow list, it's not difficult to infer the argumentdatainisDataPrepared(data)isDataPrepared.My idea is to add more logic to
narrowTypeByCallExpression, while thereferenceis a call expression and has an argument overlap with thecallExpression, we can re-calculate the return type of thereference.So my current question is: Is it possible to narrow a CallExpression
toRefs(data)with the given argument typedata? I've checked thecheckCallExpression, and the argument type narrowing seems only to happen with the identifier's flow, it seems not possible to specify a flow tocheckCallExpressionand tell it to use the flow to narrow the type.Wish I can hear some advice here, thanks
Update: Found this doc https://github.com/microsoft/TypeScript/wiki/Reference-Checker-Inference#type-parameter-inference
- added a commit that references this issue
on Aug 25, 2024 - addedDomain: check: Control FlowThe issue relates to control flow analysisThe issue relates to control flow analysis
on Oct 16, 2025
🔍 Search Terms
discriminant union, ref, control flow guard, type narrowing
✅ Viability Checklist
⭐ Suggestion
Treat types like
Ref<T>as a discriminant property in a union or find a way to narrow the type ofpayload📃 Motivating Example
This is a very common use case in the Vue Pinia state store library, millions of projects use this library and have code like
If we can improve this type narrowing behavior, the narrowed
payloadtype can helps developer write safer code than before💻 Use Cases
More detailed playground link
The use cases is actually shown in the motivating example.
I've dig into the
checker.tsfor some time and here's my findingsgetDiscriminantPropertyAccesscannot treatreadyas a discriminant property now because it needs to checkCheckFlags.Discriminantwhich impliesCheckFlags.HasLiteralType. It's a pretty strict check and as its name describes,Ref<T>has no chance to pass this check.Can we use type predicates or assert function to add more information to
payload's flow list? If it's possible, maybe we can do following steps while examine thepayloadpayload's symbol, if its declaration is aBindingPatternpayload, if the narroweddatais the initializer ofpayload's declarationpayloadbased on the narroweddata