I have a simple code:
const allTypes = { jpg: true, gif: true, png: true, mp4: true };
const mediaType = url.substring(url.lastIndexOf(\'.\') + 1).toLowerCas
You can use indexable types, but this widens the type of allTypes
to contain any (string) key, when it looks like you have a limited list of keys that you want to support.
A better solution - allowing you to use the proper type of allTypes
- is (as you already indicated in your question) to tell the compiler your assumption that mediaType
is one of the keys of the type of allTypes
with a type assertion:
return Boolean(allTypes[mediaType as keyof typeof allTypes]);
This type is in this case equivalent to the union type
"jpg" | "gif" | "png" | "mp4"
, but it is computed automatically.
(How you ensure that your assumption is correct at runtime is a separate concern, of course.)
All you need is to define the index signature:
const allTypes: {[key: string]: boolean} = { jpg: true, gif: true, png: true, mp4: true };
Similarly to how we can use interfaces to describe function types, we can also describe types that we can “index into” like
a[10]
, orageMap["daniel"]
. Indexable types have an index signature that describes the types we can use to index into the object, along with the corresponding return types when indexing. Let’s take an example:interface StringArray { [index: number]: string; } let myArray: StringArray; myArray = ["Bob", "Fred"]; let myStr: string = myArray[0];
Above, we have a
StringArray
interface that has an index signature. This index signature states that when aStringArray
is indexed with anumber
, it will return astring
.