I'm using typescript on a project and in some parts of it I have to use union types. But I'm getting some weird error messages that I don't know how to deal with. Consider the type below:
type body = {
[_: string]:
| 'boolean'
| 'number'
| 'string'
| {
type: 'boolean' | 'number' | 'string'
optional?: boolean
}
| {
type: 'array'
items: 'boolean' | 'string' | 'number'
optional?: boolean
[_: string]: any
}
}
I'm using [_: string]:
because I should be able to use any arbitrary key. The value can either be a string indicating a type or can be a object that provides more details.
Now consider the following function:
function show(data: body) {
console.log(data)
}
When I call the above function with the object below:
const data = {
username: { type: 'string', optional: false },
address: { type: 'string' },
city: 'string'
}
Typescript gives the error below:
Argument of type '{ username: { type: string; optional: boolean; }; address: { type: string; }; city: string; }' is not assignable to parameter of type 'body'.
Property 'username' is incompatible with index signature.
Type '{ type: string; optional: boolean; }' is not assignable to type '"string" | "number" | "boolean" | { type: "string" | "number" | "boolean"; optional?: boolean | undefined; } | { [_: string]: any; type: "array"; items: "string" | "number" | "boolean"; optional?: boolean | undefined; }'.
Property 'items' is missing in type '{ type: string; optional: boolean; }' but required in type '{ [_: string]: any; type: "array"; items: "string" | "number" | "boolean"; optional?: boolean | undefined; }'.
How can I solve this? thanks
data.username.type
is widened tostring
, you can check out this explanation of literal widening. TL;DR: Becausedata
is mutable, it widens the types of any literals to their more general primitive type. – Indolent