diff --git a/schemas/discriminated.json b/schemas/discriminated.json index e20a8088..51902063 100644 --- a/schemas/discriminated.json +++ b/schemas/discriminated.json @@ -180,7 +180,6 @@ }, "PlanningPermissionApplication": { "additionalProperties": false, - "description": "Application for a \"Planning Permission\" project", "properties": { "applicationType": { "const": "pp", @@ -229,7 +228,6 @@ }, "PriorApprovalApplication": { "additionalProperties": false, - "description": "Application for a \"Prior Approval\" project", "properties": { "applicationType": { "const": "pa", @@ -321,10 +319,9 @@ { "$ref": "#/definitions/NoticeWTT" } - ], - "description": "Application for a \"Works to trees\" project" + ] } }, - "description": "The root specification for a planning application in England generated by a digital planning service", + "description": "(Temporary name to not clash with the existing `Application` type)\nThe root specification for a planning application in England generated by a digital planning service", "title": "App" } \ No newline at end of file diff --git a/types/schemas/application/enums/ApplicationTypes.ts b/types/schemas/application/enums/ApplicationTypes.ts index 67a32d98..2de754ec 100644 --- a/types/schemas/application/enums/ApplicationTypes.ts +++ b/types/schemas/application/enums/ApplicationTypes.ts @@ -182,7 +182,7 @@ type GenericApplicationType = { type ExtractPrimaryKeys = T extends `${infer K}.${string}` ? K : T; -export type PrimaryApplicationTypes = ExtractPrimaryKeys; +export type PrimaryApplicationType = ExtractPrimaryKeys; type ApplicationTypeMap = { [K in ApplicationTypeKeys]: GenericApplicationType; diff --git a/types/schemas/discriminated/ApplicationData.ts b/types/schemas/discriminated/ApplicationData.ts index 7d3257d8..229a1a0a 100644 --- a/types/schemas/discriminated/ApplicationData.ts +++ b/types/schemas/discriminated/ApplicationData.ts @@ -1,26 +1,33 @@ import { ApplicationTypeKeys, - PrimaryApplicationTypes, + PrimaryApplicationType, } from '../digitalPlanningApplication/enums/ApplicationTypes'; /** * @internal + * Base type for ApplicationData. Contains all shared properties across all application types */ export interface ApplicationDataBase { applicationType: TGranular; somethingShared: string; } +/** + * @description Specific ApplicationData required for "Works to trees" applications + */ export interface WTTApplicationData { wttSpecificProperty: number; } +/** + * @description Specific ApplicationData required for "Planning Permission" applications + */ export interface PPApplicationData { ppSpecificProperty: number; } /** - * @internal + * TypeMap of PrimaryApplicationTypes to their specific ApplicationData models */ export interface ApplicationDataVariants { wtt: WTTApplicationData; @@ -29,11 +36,12 @@ export interface ApplicationDataVariants { /** * @internal + * Conditional type to return a specific or generic ApplicationData model, based on PrimaryApplicationType + * TPrimary and TGranular are both required as the granular variable is exposed, and must match the value in the Application root */ export type ApplicationData< - TPrimary extends PrimaryApplicationTypes, + TPrimary extends PrimaryApplicationType, TGranular extends ApplicationTypeKeys, > = TPrimary extends keyof ApplicationDataVariants ? ApplicationDataVariants[TPrimary] & ApplicationDataBase - : // Fallback to shared values only - ApplicationDataBase; + : ApplicationDataBase; diff --git a/types/schemas/discriminated/User.ts b/types/schemas/discriminated/User.ts index 09afce99..15d8c87b 100644 --- a/types/schemas/discriminated/User.ts +++ b/types/schemas/discriminated/User.ts @@ -1,4 +1,4 @@ -import {PrimaryApplicationTypes} from '../digitalPlanningApplication/enums/ApplicationTypes'; +import {PrimaryApplicationType} from '../digitalPlanningApplication/enums/ApplicationTypes'; export interface UserBase { role: 'applicant' | 'agent' | 'proxy'; @@ -13,7 +13,7 @@ export interface PPUser extends UserBase { } /** - * @internal + * TypeMap of PrimaryApplicationTypes to their specific User models */ interface UserVariants { wtt: WTTUser; @@ -22,9 +22,7 @@ interface UserVariants { /** * @internal + * Conditional type to return a specific or generic User model, based on PrimaryApplicationType */ -export type User = - T extends keyof UserVariants - ? UserVariants[T] - : // Default value for non-specific application types - UserBase; +export type User = + TPrimary extends keyof UserVariants ? UserVariants[TPrimary] : UserBase; diff --git a/types/schemas/discriminated/index.ts b/types/schemas/discriminated/index.ts index 02aa04f7..ce35cfbb 100644 --- a/types/schemas/discriminated/index.ts +++ b/types/schemas/discriminated/index.ts @@ -1,12 +1,18 @@ import { ApplicationTypeKeys, - PrimaryApplicationTypes, + PrimaryApplicationType, } from '../digitalPlanningApplication/enums/ApplicationTypes'; import {ApplicationData} from './ApplicationData'; import {User} from './User'; -interface GenericApplication< - TPrimary extends PrimaryApplicationTypes, +/** + * @internal + * The generic base type for all applications + * Takes a primary and granular application type which allows child properties to differ based on these inputs + * Deriving `TPrimary` from `TGranular` is possible in TS, but not in a way which is currently compatible with ts-json-schema-generator + */ +interface ApplicationSpecification< + TPrimary extends PrimaryApplicationType, TGranular extends ApplicationTypeKeys, > { applicationType: TGranular; @@ -16,45 +22,43 @@ interface GenericApplication< }; } -/** - * @description Application for a "Planning Permission" project - */ -export type PlanningPermissionApplication = GenericApplication<'pp', 'pp'>; - -/** - * @description Application for a "Prior Approval" project - */ -export type PriorApprovalApplication = GenericApplication<'pa', 'pa'>; +export type PlanningPermissionApplication = ApplicationSpecification< + 'pp', + 'pp' +>; +// TODO: All granular types -export type BaseWTT = GenericApplication<'wtt', 'wtt'>; -export type ConsentWTT = GenericApplication<'wtt', 'wtt.consent'>; -export type NoticeWTT = GenericApplication<'wtt', 'wtt.notice'>; +export type PriorApprovalApplication = ApplicationSpecification<'pa', 'pa'>; +// TODO: All granular types -/** - * @description Application for a "Works to trees" project - */ export type WorksToTreesApplications = BaseWTT | ConsentWTT | NoticeWTT; +export type BaseWTT = ApplicationSpecification<'wtt', 'wtt'>; +export type ConsentWTT = ApplicationSpecification<'wtt', 'wtt.consent'>; +export type NoticeWTT = ApplicationSpecification<'wtt', 'wtt.notice'>; /** * @title App - * @description The root specification for a planning application in England generated by a digital planning service + * @description + * (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 = | PlanningPermissionApplication | PriorApprovalApplication | WorksToTreesApplications; +// TODO: All the rest! -const test: App = { - applicationType: 'wtt.consent', - data: { - user: { - role: 'agent', - wttSpecificProperty: true, - }, - application: { - applicationType: 'wtt.consent', - wttSpecificProperty: 123, - somethingShared: 'abc', - }, - }, -}; +// const test: App = { +// applicationType: 'wtt.consent', +// data: { +// user: { +// role: 'agent', +// wttSpecificProperty: true, +// }, +// application: { +// applicationType: 'wtt.consent', +// wttSpecificProperty: 123, +// somethingShared: 'abc', +// }, +// }, +// };