I'd like to type an object that can contain any property, but if it has any of the properties a
, b
or c
, it must contain all of the properies a
, b
and c
.
In other words: the object can contain any property, but if it contains a
, b
or c
it must contain a
, b
and c
.
let something: Something;
// these should be valid:
something = { a: 1, b: 1, c:, 1 };
something = { a: 1, b: 1, c:, 1, custom: 'custom' };
something = { custom: 'custom' };
// these should be invalid:
something = { a: 1 };
something = { a: 1, b: 1 };
something = { a: 1, c: 1 };
something = { b: 1 };
something = { a: 1, custom: 'custom' };
How can this be achieved?
Creating a union type with an object seems correct, but doesn't work:
interface RequiredProps {
a: number;
b: number;
c: number;
}
type Something = RequiredProps | {};
You can create a union type, between a type that allows
a
,b
, andc
and an indexer, and one that forcesa
,b
, andc
if present to have typenever
.If you have functions that return
never
it may be possible to assign the properties but for most practical casses this should work.We could even create a generic type for this situation: