I've seen this code snippet a lot:
type RequireOnlyOne<T, Keys extends keyof T = keyof T> =
Pick<T, Exclude<keyof T, Keys>>
& {
[K in Keys]-?:
Required<Pick<T, K>>
& Partial<Record<Exclude<Keys, K>, undefined>>
}[Keys]
Here you can find the question from where I took it.
It works, however, I have this structure:
export interface MenuItems {
firstLevel: {
secondLevel: ['one', 'two']
};
anotherFirstLevel: {
anotherSecondLevel: ['one', 'two'],
oneMoreSecondLevel: null
};
}
I need to apply RequireOnlyOne
for the first and the second levels, but I can't figure what to change on the type RequireOnlyOne
so it works for each firstLevel keys but also with secondLevel keys. As it is right now I can select only one firstLevel but multiple secondLevels of that firstLevel.
I also tried to compose a new type with an object which key could be RequireOnlyOne<keyof MenuItems>
and a value that uses also RequireOnlyOne
for the values, but couldn't make it.
Example of what I want, calling the desired type as customType
:
const workingObject: customType = {
firstLevel: { // Just one property of the first level
secondLevel: ['one', 'two'] // Just one property of the second level
};
}
const errorObject: customType = {
firstLevel: {
secondLevel: ['one', 'two']
};
anotherFirstLevel: { // Should not work as I am including 2 properties for the first level
anotherSecondLevel: ['one', 'two']
};
}
const anotherErrorObject: customType = {
anotherFirstLevel: {
anotherSecondLevel: ['one', 'two'],
oneMoreSecondLevel: null // Should not work neither as I am including 2 properties for second level
};
}
The type should throw an error if the object has more than one first level property, and/or more than one second level property. With the proposed RequireOnlyOne
type I can achieve that but just for the first level, but I need the same effect for first and second level.
Any ideas?