I need to describe an interface where:
- A property with a 'billingAddress' key has a value of an Object with specific properties, and
- Properties with any other key have a value of a string.
I tried this:
interface DoesNotWork {
[key: string]: string;
billingAddress?: {
foo: string;
}
}
Typescript complains that Property 'billingAddress' of type '{ foo: string; } | undefined' is not assignable to 'string' index type
Fair enough: when DoesNotWork.billingAddress
is defined, Typescript won't know whether it should be assigned a string
, an object
or undefined
.
How do I describe the interface in a way that Typescript will understand?
CodePudding user response:
Use discriminated union so you can mix and match.
interface DoesNotWork {
billingAddress?: {
foo: string;
};
}
const foo: DoesNotWork | { [key: string]: string } = {
billingAddress: { foo: "value" },
key: "value"
};
CodePudding user response:
With using Index Signatures because the exact propertyName is not known at compile-time, but the general structure of the data is known, creating a separate interface, to accommodate this data, and afterward composing the Interfaces to achieve the desired object structure, should help solve your problem OR extend using union types to increase the flexibility of values which are expected
This is because in trying to define different fields in the same interface, then you must cater for the option, of different (values) for the other fields aside from the Index Signature field
demo code
//composition approach(1)
interface BillingAddress{
foo: string;
}
interface DoesNotWork{
[key: string]: string;
}
interface ComposedInterface{
indexSignature: DoesNotWork,
billingAddress? : BillingAddress,
}
//extending value fields using unions approach(2)
interface BillingAddress{
foo: string;
}
interface DoesNotWork{
[key: string]: string | BillingAddress;
billingAddress: BillingAddress;
}