Consider the following code. The function getStatusDescription
return a description for a given HTTP code if it's found, otherwise return the status code itself.
const StatusDescription = {
200: 'ok',
400: 'bad request',
500: 'internal server error',
}
const getStatusDescription(status: string) = {
return StatusDescription[status] || status
}
Return line gives an error:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ 200: string; 400: string; 500: string; }'.
No index signature with a parameter of type 'string' was found on type '{ 200: string; 400: string; 500: string; }'. (7053)
A possible fix is to set StatusDescription: Record<string, string> = …
, but this would wide the Object's key type to all string possibles, which is undesired.
I tried to use return status in StatusDescription ? StatusDescription[status] : status
, but TypeScript gives the same error. So I have to manually convert types:
return (
status in StatusDescription
? StatusDescription[status as unknown as keyof typeof StatusDescription]
: status
)
Which is very verbose. Or, to make it shorter, and maybe more wrong:
return (
StatusDescription[status as unknown as keyof typeof StatusDescription]
|| status
)
It doesn't give any error, but it seems wrong since we don't really know if status
is a keyof StatusDescription
at the point the conversion is made.
Is there a non-verbose alternative (comparable to obj[key] || key
) without loosing types?
CodePudding user response:
You might want a map which could help with all those verbose casts:
// type is now Map<string, string>
const StatusDescription = new Map(Object.entries({
200: 'ok',
400: 'bad request',
500: 'internal server error',
}));
const getStatusDescription(status: string) = {
// simple get
return StatusDescription.get(status) ?? status;
}
// for normal access you can assert that it exists with '!'
StatusDescription.get(500)!;
??
is nullish coalescing which you can find more about here.