I am currently working on building an interface that will include mandatory fields based on the value of another field.
For instance:
const schema = {
str: { type: 'string' },
nbr: { type: 'number' },
bool: { type: 'boolean' },
date: { type: 'date' },
strs: { type: ['string'] },
obj: { type: 'object' },
} as ISchema;
In the above code snippet, I want the system to notify me if the obj
field is missing a property because its value for type
is set to 'object'
.
After some trial and error, I managed to achieve this using the following code structure:
interface SchemaOptionsObject {
type: 'object' | ['object'] ;
properties: ISchema;
}
interface SchemaOptionsString {
type: 'string' | ['string'] ;
}
interface SchemaOptionsNumber {
type: 'number' | ['number'] ;
}
interface SchemaOptionsBoolean {
type: 'boolean' | ['boolean'];
}
interface SchemaOptionsDate {
type: 'date' | ['date'] ;
}
type SchemaOptions = SchemaOptionsString | SchemaOptionsNumber | SchemaOptionsBoolean | SchemaOptionsDate | SchemaOptionsObject;
export interface ISchema {
[key: string]: SchemaOptions;
}
However, I noticed that my solution involved a lot of repetition. In an attempt to optimize the code, I encountered a challenge:
export type SchemaAllowedTypes = 'string' | 'number' | 'boolean' | 'date' | 'object';
type SchemaOptionsObject<T extends SchemaAllowedTypes> =
T extends 'object' ?
{ properties: ISchema } :
{};
type SchemaOptions<T extends SchemaAllowedTypes> = {
type: T | T[];
} & SchemaOptionsObject<T>;
export interface ISchema {
[key: string]: SchemaOptions<SchemaAllowedTypes>;
}
It seems that the code snippet above does not work as expected due to the restriction imposed by T extends 'object'
. Is there any specific keyword that can help me validate the value of T
in this scenario?
Do you think I am approaching this problem in the wrong way? Your assistance would be greatly appreciated!
Thank you for your support!