You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Set.has() and Array.includes() should narrow the type of their argument to the type of this when they return true #51678
My compilation target is ES2022 and my lib is the default.
Missing / Incorrect Definition
Set.has() and Array.includes() should narrow the type of their argument to the type of this when they return true (which implies they should accept wider types as arguments).
This is probably impossible until #14520 is solved, but I wanted to add a more concrete use case than just making it convenient to pass wide arguments.
Sample Code
typeIngredient={amount?: string;unit?: string;name?: string;}constingredientKeys=newSet(["amount","unit","name"]asconst);letkey: string="...";letvalue: string="...";letresult: Ingredient={};// Doesn't work but should:if(ingredientKeys.has(key)){result[key]=value;}// Works, but can't do it as a member function:functionhas<TextendsU,U>(set: ReadonlySet<T>,elem: U): elem is T{constwider: ReadonlySet<U>=set;returnwider.has(elem);}if(has(ingredientKeys,key)){result[key]=value;}
If you mean the requirement that type predicates be exhaustive, that is documented, albeit admittedly somewhat offhandedly:
Notice that TypeScript not only knows that pet is a Fish in the if branch; it also knows that in the else branch, you don’t have a Fish, so you must have a Bird.
which implies the type predicate must be exhaustive.
Is this that complicated? This seems to fulfill the requirement already:
/** Shouldn't this be the type signature of Array.prototype.includes? */functionarrayIncludes<T>(arr: T[],v: unknown): v is T{returnarr.includes(vasT);}
I assume I am missing something but couldn't the type signature simply be changed to this?
There's a code snippet in this comment that shows why you can't do this, but explicitly:
Type predicates also narrow in the false case. If Array.includes(val) returns true then sure, the type of val could be narrowed to the type of the array elements. But if it returns false, then it is rarely correct to narrow val to exclude the type of the array elements. The only time this is even remotely acceptable would be if the array element type is a union of unit/literal types, and if the array is somehow known to contain an element for each and every member of that union.
Without direct support for #14520 and #15048, writing a version of this that doesn't have weird side effects is ugly, and not anything the TS team wants to merge into the standard library. This is mostly all covered in #36275.
Reacted by Bruce Pascoe, Joe Desmond and Dominic Victoria
To be clear, #15048 is required for the reasons explained by Joe Calzaretta (@jcalz). #14520 is optional (the alternative is to type the search term as unknown), but most people still want it to be error to check for an unrelated type in an array, so strArray.includes(num) should be an error, but strArray.includes(strOrNum) shouldn't. Without #14520 you only have the choice of both being an error, or neither.
Activity
jyasskin commentedon Nov 29, 2022
Yikes, this also requires #15048 even though that behavior isn't documented in https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates.
fatcerberus commentedon Nov 29, 2022
If you mean the requirement that type predicates be exhaustive, that is documented, albeit admittedly somewhat offhandedly:
which implies the type predicate must be exhaustive.
jcalz commentedon Nov 29, 2022
Essentially a duplicate of #36275
MoritzKn commentedon Nov 29, 2022
Is this that complicated? This seems to fulfill the requirement already:
I assume I am missing something but couldn't the type signature simply be changed to this?
jcalz commentedon Nov 29, 2022
^ #36275 (comment)
There's a code snippet in this comment that shows why you can't do this, but explicitly:
Type predicates also narrow in the
falsecase. IfArray.includes(val)returnstruethen sure, the type ofvalcould be narrowed to the type of the array elements. But if it returnsfalse, then it is rarely correct to narrowvalto exclude the type of the array elements. The only time this is even remotely acceptable would be if the array element type is a union of unit/literal types, and if the array is somehow known to contain an element for each and every member of that union.Without direct support for #14520 and #15048, writing a version of this that doesn't have weird side effects is ugly, and not anything the TS team wants to merge into the standard library. This is mostly all covered in #36275.
fatcerberus commentedon Nov 29, 2022
I think this Playground illustrates the issue with that signature nicely.
Or even better, this one: Playground
fatcerberus commentedon Nov 29, 2022
To be clear, #15048 is required for the reasons explained by Joe Calzaretta (@jcalz). #14520 is optional (the alternative is to type the search term as
unknown), but most people still want it to be error to check for an unrelated type in an array, sostrArray.includes(num)should be an error, butstrArray.includes(strOrNum)shouldn't. Without #14520 you only have the choice of both being an error, or neither.typescript-bot commentedon Dec 4, 2022
This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.
* change the height of `.post-nav(-expand)?` from fixed `height: 100v…
* move `subParam.not` from `UnknownParam` in `useQueryForm.ts` to `Ad…