The issue arises from the requirement for the index signature to be compatible with all named properties in the interface. One solution is to include boolean
in the index signature:
interface FormData {
[key: string]: string | boolean;
loading: boolean
}
Another approach is to use an intersection type. Intersections do not enforce compatibility between the index and other properties:
type FormData = {
[key: string]: string;
} & {
loading: boolean
}
However, there are drawbacks to this method:
- No object literal can match this type without explicit assertion, resulting in an error when assigning a
boolean
value to a key of string
- Dynamic access using a key may lead to inconsistencies between the static type and runtime type if the key happens to be
'loading'
For example:
let formData = {
loading: true
} as FormData
let value = formData['loading'] // boolean
let dynamicKey = 'loading' as string;
let value2 = formData[dynamicKey] // string