Consider a simple indexed interface:
interface FormData {
[K: string]: string;
}
That lil' guy works great. But, there is a circumstance where I'd like to allow a property to be an array of strings.
interface AcmeFormData extends FormData {
foobar: string[];
}
Typescript complains with
Property 'foobar' of type 'string[]' is not assignable to string index type 'string'.
Looking through the docs, it seems like the following should be possible, but also complains.
interface FormData {
[K: string]: string;
foobar: string[];
}
It should be noted that I'd like to avoid using a union type ([K: string]: string | string[];
) because 99% of the time, the data will always be a single string value and therefore would like to avoid having to type hint.
Is this possible? Or am I trying to abuse Typescript?
You can do this by using an intersection, instead of using extends
. EG:
interface FormData {
[K: string]: string;
}
type AcmeFormData = FormData & { foobar: string[] };
declare const test: AcmeFormData;
test.foobar // string[]
test.anythingelse // string
However, this does lead to some issues that you need to be careful around, since now the index signature is no longer accurate. So when typescript infers something using that signature, you need to be aware that it will be wrong:
for (let key in test) {
// val is inferred to have type string, but be careful!
// In truth, val will be a string[] for the 'foobar' key,
// but typescript is no longer aware of that. So this will
// create a runtime error, but compiles without problems!
const val = test[key].toLowerCase();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With