-
-
Notifications
You must be signed in to change notification settings - Fork 672
types: Use a distinct UserId type for user IDs. #4421
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
Merged
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
d4dc9c2
typing-status tests: Make test data less ad-hoc.
gnprice d11911a
recipient [nfc]: Mark an array parameter read-only.
gnprice a171a05
api: Cut unused, unimplemented user-groups bindings.
gnprice d4c57b6
api types [nfc]: Move import to above a section heading.
gnprice c4c39ca
api types: Add UserId, an opaque type alias; don't use it yet.
gnprice f59cd48
user types: Use the new UserId alias in exampleData.
gnprice 62d48a7
user types: Use makeUserId in test code.
gnprice 11f5b83
user types: Use makeUserId when parsing a user ID from a string.
gnprice 1170499
user types: Use makeUserId in our fake-yet-not-test data.
gnprice 31e0e3f
api types: Use UserId in most of the API.
gnprice 075d971
user types: Use UserId for PM recipients.
gnprice 19c8189
user types: Use UserId for "own user ID" data.
gnprice 15ab4d8
user types: Use UserId in initial PM-conversations data.
gnprice 78cdd5e
user types: Use UserId in user-status data.
gnprice 109bc35
user types: Use UserId for unreads data.
gnprice b3b2599
user types: Use UserId for typing-status state.
gnprice b950e25
user types: Use UserId in MentionWarnings component.
gnprice 91b8572
user types: Switch to UserId in most React props and state.
gnprice 9f53018
user types: Use UserId in pmKeyRecipientsFromIds.
gnprice 3219710
user types: Propagate UserId type through outbound typing-status.
gnprice 9d12a96
user types: Consume UserId in two user-data selectors.
gnprice a8b3a21
user types: Switch to UserId in getAllUsersById and friends.
gnprice 7fb49af
user types: Use UserId for sending a PM, in sharing code.
gnprice 1680f7b
api types: Require UserId on input to the API, completing the convers…
gnprice File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| /* @flow strict-local */ | ||
|
|
||
| /** | ||
| * A user ID. | ||
| * | ||
| * This is a number that identifies a particular Zulip user. Different | ||
| * users on the same Zulip server will have different user IDs. On the | ||
| * other hand, between different Zulip servers the same user ID may be used | ||
| * to refer to completely unrelated users. | ||
| * | ||
| * In general, if something calls for a value of this type, then you should | ||
| * be getting it from something that already has this type: like the | ||
| * `user_id` property of a `User` object, or a data structure that stores | ||
| * user IDs. | ||
| * | ||
| * The only other way to create a `UserId` is to call the `makeUserId` | ||
| * function provided by this module. | ||
| * | ||
| * See also type `User`, for the thing that one of these identifies. | ||
| */ | ||
| // How this type works: it's an "opaque type alias" for simply a number. | ||
| // See Flow docs: https://flow.org/en/docs/types/opaque-types/ | ||
| // | ||
| // This means that: | ||
| // * At runtime, a `UserId` value is just a number. The use of `UserId` | ||
| // involves zero runtime overhead compared with simply `number`. | ||
| // * Because we've written a "bound" of `: number`, all code that has one | ||
| // of these values can freely use it as if it were simply `number`. | ||
| // * On the other hand, the only way to *create* such a value is to invoke | ||
| // something from this module to do it for you. | ||
| // | ||
| // For more background discussion of opaque types, see `PmKeyRecipients`. | ||
| export opaque type UserId: number = number; | ||
|
|
||
| /** | ||
| * Take a number, and declare that it truly is a user ID. | ||
| * | ||
| * This does nothing at all at runtime, just returning the value it's | ||
| * passed. Its only effect is to inform the type-checker that it's OK to | ||
| * use this value where a user ID is required. | ||
| * | ||
| * In general the only legitimate use case for this function, outside of | ||
| * tests, is when parsing a user ID from a string. When getting a user ID | ||
| * from any other source, if the values really are user IDs then the type of | ||
| * that source should be adjusted to say so. | ||
| */ | ||
| export const makeUserId = (id: number): UserId => id; | ||
|
|
||
| /* Possible future work: | ||
| export opaque type StreamId: number = number; | ||
| export opaque type MessageId: number = number; | ||
| export const makeStreamId = (id: number): StreamId => id; | ||
| export const makeMessageId = (id: number): MessageId => id; | ||
| */ | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Do you think it'll always be pretty clear whether a given ID type belongs here in src/api/idTypes.js, vs. somewhere else?
I'm thinking of the return value of
keyFromNarrow, which we've discussed making an opaque type for. I think that pretty clearly belongs right alongsidekeyFromNarrow, in narrows.js. I think I'd say it doesn't belong in src/api because we never pass those keys to the API, and we never receive them from the API. We do pass the result ofapiNarrowOfNarrowto the API.I think this is a sensible criterion for putting ID types in src/api/idTypes.js: if we ever talk to the API using that type of ID, its opaque type should live here. Perhaps that goes without saying, but we do a lot of passing-around of IDs within the app (including of user IDs, stream IDs, and our own narrow keys), so I wonder if a small comment might be helpful. 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The basic principle is that
src/api/is self-contained, so that code there shouldn't import code elsewhere -- it's describing the server API, and behaves like an independent library for doing that. We've made a few exceptions to that principle for convenience, but are generally pretty consistent about it.So that means that any type that's going to be used in the API should be defined in the API part of the code. If we introduce a
StreamIdorMessageId, we'll want to use it in the API, so it'll be defined there.The narrow-keys returned by
keyFromNarrowdon't appear in the API; they're our own invention for within the app. So they naturally wouldn't be defined insrc/api/, and instead would appear innarrows.jsas you say.Because this is a more general principle I don't think it calls for a comment on this specific instance. But it'd be good to write down that general principle, which I'm not sure we have. Any suggestions on where would be most helpful?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, thanks! I've just merged ba7108f, wiki-style.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, thanks!