'Typescript: Ensure a type has a property A if it also has property B
I have a type that looks like something as follows:
type MyType = {
a: string;
b: string;
c?: number;
d?: string;
}
There are objects of this type which can look like:
const myObj1: MyType = { a, b };
const myObj2: MyType = { a, b, c, d };
So if an object of MyType has the property c, it will definitely have property d. Is there a way to define this type as such that I do not have to non-null assert or check for both types other than extending the type into a different type?
Solution 1:[1]
If you're allowed to change MyType, one approach is to separate the c and d properties into a different object where they're required, and alternate with an intersection with that object.
type AB = {
a: string;
b: string;
};
type MyType = AB | AB & {
c: number;
d: string;
}
This way, if something of MyType is seen to have a c property, TypeScript will see that it definitely also has a d property.
Solution 2:[2]
If you want property 'd' to exist only when 'c' is defined and vice-versa, it would be worth using extended interfaces and overwriting the optional properties as never as follows:
type Base = {
a: string;
b: string;
c?: number;
d?: string;
}
interface Concrete1 extends Base {
c?: never;
d?: never;
}
interface Concrete2 extends Base {
c: number;
d: string;
}
type MyType = Concrete1 | Concrete2;
const myObj1: MyType = { a: 'a', b: 'b' }; ?
const myObj2: MyType = { a: 'a', b: 'b', c: 2 }; ?
const myObj3: MyType = { a: 'a', b: 'b', c: 2, d: 'd' }; ?
This will ensure that an object of MyType always contains either a, b or a,b,c,d properties.
Link to the playground.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | CertainPerformance |
| Solution 2 | Ovidijus Parsiunas |
