-
Notifications
You must be signed in to change notification settings - Fork 2
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: Initial setup of a generic application type #215
Conversation
be6815f
to
c54ab40
Compare
type ExtractPrimaryKeys<T> = T extends `${infer K}.${string}` ? K : T; | ||
|
||
export type PrimaryApplicationTypes = ExtractPrimaryKeys<ApplicationTypeKeys>; |
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.
Before hitting on this I spent a bit of time working on constructing the list of keys using string literal types which was the approach we originally discussed.
type PrimaryAmendment = 'amendment';
type SecondaryAmendment = 'minorMaterial' | 'nonMaterial';
type Amendment =
| PrimaryAmendment
| `${PrimaryAmendment}.${SecondaryAmendment}`;
This felt like a pretty nice approach and did work (see tooltip in above screenshot), but had a few shortcomings compared to the approach using infer
.
- It's a whole lot more verbose
- It lends itself very well to easily setting up a large number of permutations. Our list of application types doesn't match this pattern - for example the
pp
list has many unique combinations of secondary and tertiary keys. - It makes the "enum" of application types harder to parse and understand (and maintain?)
Here's the infer
approach in action -
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've actually had to revisit this approach. Despite this being valid TypeScript, I've not found a meaningful way for ts-json-schema-generator
to parse this - the combination of infer
and template literal types isn't currently supported.
I've resorted to a more verbose, but perfectly workable, approach where we need to provide both the primary and granular variables.
b77604b
to
c54ab40
Compare
types/schemas/discriminated/index.ts
Outdated
TPrimary extends PrimaryApplicationType, | ||
TGranular extends ApplicationTypeKeys, | ||
> { | ||
applicationType: TGranular; |
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 is required to be above or at an equal hierarchy level of anywhere TGranular
or TPrimary
is passed in.
This means if we need variants based on TGranular
or TPrimary
outside of data.application
(I think we do?), we can't just keep this in data.application.applicationType
.
* Base type for ApplicationData. Contains all shared properties across all application types | ||
*/ | ||
export interface ApplicationDataBase<TGranular extends ApplicationTypeKeys> { | ||
applicationType: TGranular; |
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.
TGranular
is repeated here in order to make this change slightly less disruptive. Note that this is just the string value and not the value/description object (we could still support this!).
types/schemas/app/ApplicationData.ts
Outdated
} from '../digitalPlanningApplication/enums/ApplicationTypes'; | ||
|
||
/** | ||
* @internal |
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.
types/schemas/app/index.ts
Outdated
|
||
export type WorksToTreesApplications = ApplicationSpecification< | ||
'wtt', | ||
Extract<ApplicationTypeKeys, 'wtt' | 'wtt.consent' | 'wtt.notice'> |
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 is a really neat solution (thanks again @jessicamcinchak!) and again points towards a simpler way of encoding enums, e.g.
type WTTApplicationType =
/**
* @description Something
*/
| "wtt"
/**
* @description Something else
*/
| "wtt.consent"
/**
* @description Something else again
*/
| "wtt.notice";
type ApplicationType = WTTApplicationType | PPApplicationType | PAApplicationType;
export type WorksToTreesApplications = ApplicationSpecification<
'wtt',
WTTApplicationType
>
This would solve the issue of missing or mismatched types, and having to repeat them here, if they were just defined once. I'll take a closer look at this in another PR.
689bd64
to
2300112
Compare
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.
A bit hard to review this one as I think a lot of your initial comments/questions are now outdated - but this looks really good and very nice to be able to play with this setup without fully replacing existing Application
schema yet - so I say ready to merge/fix forward on main
whenever 👍
types/schemas/app/index.ts
Outdated
* (Temporary name to not clash with the existing `Application` type) | ||
* The root specification for a planning application in England generated by a digital planning service | ||
*/ | ||
export type App = |
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.
nit: can we call this "NextApp" or "TestApp" or "PrototypeApp" or something similar that makes it clear it's work-in-progress adn not just short-hand for existing "Application" ?
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.
Very good shout - will make this change before I merge.
What does this PR do?
pp
frompp.full.minor.technicalDetails
)Why is this necessary?
Next steps...
DigitalPlanningApplication
schema