-
Notifications
You must be signed in to change notification settings - Fork 213
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
(feat) Add common typings for patient and person #1001
Conversation
Size Change: -383 kB (-10.02%) 👏 Total Size: 3.44 MB
ℹ️ View Unchanged
|
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.
Generally LGTM. Are these mostly copied out of the work we did in service queues? I'd want to validate that these interfaces exactly match the REST responses - can you confirm?
attributeType: OpenmrsResource; | ||
display: string; | ||
uuid: string; | ||
value: string | number; |
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.
I don't think this is necessarily accurate. Can you check on this typing for value?
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.
you're right. This should be a string.
Yeah, most of these were from when we were making these types together in the service queues module months ago. |
One issue here is how we handle the difference between different representations. I'm not even necessarily thinking about custom representations, but, e.g., the default REF format for a person (which is returned in some circumstances): interface Person {
uuid: string;
display: string;
links: Array<{ rel: string; uri: string; resourceAlias?: string; }>;
} |
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.
Couple of quick thoughts here to make the types a little more reflective of the API.
deathDate: string; | ||
causeOfDeath: Concept; |
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.
deathDate: string; | |
causeOfDeath: Concept; | |
deathDate: string | null; | |
causeOfDeath: Concept | null; |
names: Array<PersonName>; | ||
addresses: Array<PersonAddress>; | ||
attributes: Array<PersonAttribute>; | ||
birthtime: string; |
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.
birthtime: string; | |
birthtime: string | null; |
birthtime: string; | ||
deathdateEstimated: boolean; | ||
causeOfDeathNonCoded: string; | ||
links: Array<any>; |
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.
Links are always in this format:
export interface Link {
rel: string;
uri: string;
resourceAlias?: string;
}
links: Array<any>; | |
links: Array<Link>; |
dead: boolean; | ||
deathDate: string; | ||
causeOfDeath: Concept; | ||
preferredName: PersonName; |
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.
Technically, this will be:
preferredName: PersonName; | |
preferredName: Pick<PersonName, 'uuid' | 'display' | 'links'>; |
Unless v=full
is supplied.
attributes: Array<PersonAttribute>; | ||
birthtime: string; | ||
deathdateEstimated: boolean; | ||
causeOfDeathNonCoded: string; |
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.
This one is also nullable.
@mseaton these interfaces are definitely incomplete (for example, Patient has a
@ibacher Thanks for the suggestions. Unless a field's type can change based on the representation, this should be ok right? I think it'll still helpful to see what fields are available for each type while having the expectation that it's up to the implementor to verify that the fields they need are indeed there. |
I'm not really too concerned about that (it's fully possible with interface Person extends Pick<FullPerson, 'uuid' | 'display'>, Partial<Omit<FullPerson, 'uuid' | 'display'>> {} Because that would kind of force using something like: const patientName: string = patient.person.preferredName ?? patient.person.name?[0] ?? 'UNKNOWN'; |
I don't like having that forcing everywhere, but I think we can try it and remove it later if we want (easier to go from restrictive to loose, instead of vice versa). So how about something like this pattern? I think having every attribute being // this already exists:
export interface OpenmrsResource {
uuid: string;
display?: string;
[anythingElse: string]: any;
}
// we add this as the base type for almost everything
export interface OpenmrsResourceStrict {
uuid: string;
display?: string;
links?: Array<Link>;
}
interface Person extends OpenmrsResourceStrict {
// everything with a '?'
givenName?: string;
familyName?: string;
...
} |
I'm not hugely enamored with my own proposal, but I think that having the type system setup like that will help some of our community developers do the right thing. And, yeah, I'm happy with the pattern you suggest. |
@@ -0,0 +1,5 @@ | |||
import { type OpenmrsResource } from './openmrs-resource'; | |||
|
|||
export interface Concept extends OpenmrsResource { |
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.
Does this need to be OpenmrsResourceStrict
too? Should it have more properties?
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.
Not every type needed by the Patient type (directly or transitively) is completely typed yet. Specifically this Concept
type and the User
type below are just using OpenmrsResource
as a flexible placeholder for now, while still being more correct than any
. A completely typed type should extend OpenmrsResourceStrict
instead. This convention should allow us to add more typings piecemeal.
Thanks @chibongho! I think this actually helps solve a long-standing problem we've had with types returned from APIs. |
Requirements
feat
,fix
, orchore
, among others). See existing PR titles for inspiration.For changes to apps
If applicable
Summary
Screenshots
Related Issue
Other