Skip to content

Add separate types for Collection first()/last() with zero arguments #1653

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

Closed
wants to merge 1 commit into from
Closed

Conversation

augustl
Copy link
Contributor

@augustl augustl commented Nov 27, 2018

When the type is first<NSV>(notSetValue?: NSV): V | NSV, the type of
the return value will always be V | NSV and you will have to handle
the possibility of the return value as being both of type V and
NSV. When you call first without specifying the type, it will default
to the type {}.

An example:

List<String>(["a", "b", "c"]).first().length // Will fail

List<String>(["a", "b", "c"]).first<string>().length // Will succeed

This patch will make the first succeed, by letting the type system
know that if no argument is passed to first(), the type will be String
in this case.

Copy link

@asazernik asazernik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Could you apply the same fix to immutable.js.flow?

@augustl
Copy link
Contributor Author

augustl commented Nov 28, 2018

Glad to help :) Force pushed an updated commit!

I'm not much of a flow user (and, frankly, quite the beginner in typescript as well), so the tests are passing, and "it looks good to me (tm)", but the flow part of this patch comes without warranty :)

(Not quite sure why the travis build failed, it worked yesterday, and it works on my machine if I do npm run test)

@asazernik
Copy link

Looks good to me! On the more fundamental stuff like this, flow and TS are basically identical.

@augustl
Copy link
Contributor Author

augustl commented Nov 29, 2018

Cool!

Not sure what to do about the failing tests. npm run test works fine on my machine, if I do yarn install I get the same error as in travis (error An unexpected error occurred: "https://registry.yarnpkg.com/flatmap-stream/-/flatmap-stream-0.1.1.tgz: Request failed \"404 Not Found\"".).

@augustl
Copy link
Contributor Author

augustl commented Nov 30, 2018

Found the cause of the build error, created a separate pull request #1656 for that. Will rebase this pull request against master whenever master is updated :)

Copy link
Collaborator

@leebyron leebyron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So far the existing signature has worked since not providing the optional argument causes NSV to take the value undefined, which appropriately matches the type signature for get (get(key: K): V | undefined) since the collection could be empty.

Should this new type signature explicitly include | undefined like the type signature for get? Or are you proposing weakening the types for first() and last()? If so would you also propose weakening them consistently throughout other type signatures which could return undefined for empty collections?

@@ -3878,15 +3878,17 @@ declare module Immutable {
* In case the `Collection` is empty returns the optional default
* value if provided, if no default value is provided returns undefined.
*/
first<NSV>(notSetValue?: NSV): V | NSV;
first<NSV>(): V;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be V | undefined?

@augustl augustl closed this Jan 7, 2019
When the type is `first<NSV>(notSetValue?: NSV): V | NSV`, the type of
the return value will always be `V | NSV` and you will have to handle
the possibility of the return value as being both of type V and
NSV. When you call `first` without specifying the type, it will default
to the type {}.

This patch changes the type of `first` without a type argument to be
that type or undefined, instead of that type or NSV, which defaults to
`{}` when not specified.
@augustl
Copy link
Contributor Author

augustl commented Jan 7, 2019

Very good point! That makes this patch much less important, I agree that the correct type is V | undefined and not just V. I updated the pull request and rebased it against master so the build doesn't fail, and I suppose V | undefined is marginally better than V | NSV.

@augustl augustl reopened this Jan 7, 2019
@augustl
Copy link
Contributor Author

augustl commented Jan 8, 2019

I just found a case where the explicit typing of first() with no arguments to V | undefined is needed, actually.

const xs = List<Foo>(...)
const firstX = xs.first()

firstX ? firstX.thing() : somethingElse

Currently, the type of firstX is {} | Foo inside the "if" portion of the ternary, whereas with this patch the type is Foo | undefined so Typescript knows that firstX is now just Foo.

Temporary workaround is to use get(0) instead.

@leebyron leebyron closed this Jun 17, 2021
@leebyron leebyron deleted the branch immutable-js:master June 17, 2021 22:56
@augustl
Copy link
Contributor Author

augustl commented Jun 25, 2021

Fixed in #1676 ftr :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants