-
Notifications
You must be signed in to change notification settings - Fork 12.8k
T[]
still inferred as (T | undefined)[]
even after filtering out undefined entries explicitly
#45097
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
T | undefined
even after filtering out undefined entries explicitly(T | undefined)[]
even after filtering out undefined entries explicitly
(T | undefined)[]
even after filtering out undefined entries explicitlyT[]
still inferred as (T | undefined)[]
even after filtering out undefined entries explicitly
This is working as intended. Your arrow function passed to You can make the function a type-guard by adding an explicit type annotation: You're also interested in #38390. |
@MartinJohns I'm sorry but... how's that acceptable to be "working as intented"? As I understand Typescript should work on top of Javascript, and obviously it isn't. The typing of the filter's predicate function is obviously the culprit here, instead of having the return value to be You're asking me to do: const isModel = (model: any) model is Model => model !== undefined
array.filter(isModel) but actually there are 2 issues with this:
|
I'd say it's actually more a design limitation. But the last word lies with the TypeScript team.
I'm not sure what your point is. It is working on top, your issue is purely related to TypeScripts type-system. This is no different than trying to assign a
The typing of the predicate function is fine. If you pass a type-guard, then it will narrow the type accordingly. But just assuming any returned
This is not what I suggested. In your example the
I commonly have a
See above. It is working if you pass a type predicate, but a function returning I'd like to point you again to the issue #38390. This feature requests asks for TypeScript to automatically infer simple arrow functions to type-predicates instead of functions returning |
But it's not working as intended... ...especially as per Javascript's filter function definition in the original spec. From Javascript's PoV, a type guard is just any other function and the fact that we need to arrange our code to make it work with Typescript breaks the promise of "All valid JavaScript code is also TypeScript code." which is written on the Typescript's website home page. If anything, this workaround (type guards being built in JavaScript) is just coincidental and just masks the fact that we can't make use of javascript as we could naturally do in standard javascript. I'm basing this reflection on the obligation that, when filling for a feature request, we are to tick boxes such as:
...and to be fair passing a type guard function in the
I'm genuinely sorry for overseeing this one, but still doesn't make a solid point for why the TS team should not solve the issue. I understand you guys may have bigger/more interesting problems at heart, but following the ecma spec should be a first priority which isn't followed at the moment (imho)
Thank you for pointing me to this. I understand how you can see it related but to me it's just besides the point. Point being that the filter function's definition from the ecma spec is clear: the predicate should return a value which can be coerced as a boolean, and that's all about it. There's no concept of type guards, so while i can understand that The issue i'm trying to raise is about the fact that the predicate function's possible returned type should be a boolean (or coercible boolean), and that the filter's return type should be expanded according to the type of the array itself and the predicate function's body. To be more in the solution-making mindset, as a TS user I'd expect that if Typescript is smart enough to narrow down types in code blocks based on inline expressions such as (this) const foo: string | undefined = "test"
if (foo !== undefined) {
// type of foo is "string", not "string | undefined"
foo.toLowerCase() // no need for `?`
} ...then this same logic could be applied to compute the returned type of the array as a result from the filter function, ultimately understanding that if an array of type |
... It helps if you continue reading: "You might get type-errors, [...]" - This is what you get here: A type error. I don't understand why you continue to cite JavaScript or the ECMA spec when this is purely a TypeScript issue. Your code will compile (assuming See also this answer on StackOverflow by Ryan.
Of course there is no mention of a type predicate, because that's a TypeScript construct. And what you cite here is still completely unrelated to the issue at hand. Change your code to this:
Should the type now still be The point that still stands is that TypeScript can't make type-assumptions from a function returning a By providing a type-guard that says "this value is never
... Which is exactly what the issue I linked covers. Currently |
For cases like these we have a predefined generic type-guard:
then you can just
which seems like a better approach than ad-hoc type-guards. |
@nicu-chiciuc Just as I suggested earlier already, but it didn't satisfy him. :-) |
I'm probably lost in deep technical concepts of the TS language/compiler, so please excuse my following questions if they seem stupid π Please trust that I'm not hostile and i genuinely appreciate the time you spend in answering, but if i keep going if mainly because i don't understand why you're pushing back in "use a type guard" when it should be fixed on TS's side. To be clear it's not my intent to troll this thread (in case you might think so π ). I'm just overall puzzled on why this is not working as it should from the start ; why do TS users have to bare creating a spare function as a workaround for something that works fine in pure JS? (and why do i need to waste time to explain to my more junior devs "yeah we do like this because... it's a TS thing π€·ββοΈ" for which they responded a equally puzzled "ah... ok... π")
I do understand your point being about this being Typescript issue (and overall i do agree, it is a Typescript issue otherwise i wouldn't report it in this repo) ; I keep bringing it because the Typescript issue you're describing brings a breaking change compared to what's naturally possible in JS, so i think it's necessary for the conversation to bring in the JS spec to explain why it should be fixed (it's context at this point). Saying "no biggie use a type guard" isn't good enough imho. It is a Typescript issue which breaks what we're normally able to do in JS, and therefore it should be addressed (especially .filter being a method of array, which a basic very used data structure) and so reminding of the spec helps to remind what is the natural expectations of the language.
If there's no type narrowing produced by the filter function i don't see why the type of the array should be changed. A
I understand that, and i understand that's what Type guards are supposed to do, but in the end if TS can do type inference based on an expression in in an inline Thank you overall. |
@GabrielUrbina thanks for this :) it has been suggested by @MartinJohns and @nicu-chiciuc before ; my following comments are about understanding why this bug should be fixed in userland and not implemented by default in Typescript since it's a thing we can do natively in JavaScript |
I share your opinion, that it would be great to have that inference in the filter method, however, I see it as a missing feature, due to design limitation, rather than a defect. This limitation is why I created a library for making it easier to handle. On the bright side, I think we are moving to a direction where this will be possible, in TS 4.4 we can have these alieased conditions on variables |
The specific design limitation here is that, even if TS could infer type predicates, When you do this using an |
@fatcerberus Thanks for explaining the |
Bug Report
π Search Terms
filter Boolean undefined
π Version & Regression Information
β― Playground Link
Playground link with relevant code
π» Code
π Actual behavior
values
is of type(Model | undefined)[]
even though undefined values are excluded thanks to the filter functionπ Expected behavior
values
should be of typeModel[]
The text was updated successfully, but these errors were encountered: