How do I access object fields in TypeScript using array notation
I ran into an interesting problem while converting a React app from JavaScript to TypeScript when I ran into some code using array notation to access object fields. The project I was working on had an object defined as follows.
primary: {
lighter: blue[0],
100: blue[1],
200: blue[2],
light: blue[3],
400: blue[4],
main: blue[5],
dark: blue[6],
700: blue[7],
option700: blue[7],
darker: blue[8],
900: blue[9],
contrastText
},
In the component using this, it was being accessed using array notation.
setOptions((prevState: any) => ({
...prevState,
colors: [theme.palette.primary.main, theme.palette.primary[700]],
// ...
});
I had mentioned in a previous article that I had changed this same line of code to use a new field I defined on the type as color700. I since wanted to find the TypeScript way to access fields via array notation, and I came up with the following code that makes this TypeScript friendly.
type ObjectKey = keyof typeof theme.palette.primary;
const option700 = '700' as ObjectKey;
We start by declaring a key on the type of theme.palette.primary. This construct gives us the ability to designate fields using a string as a key to index the object. As seen in the second line, we declare “700” as the object key we want to look up. TypeScript understands we’re now using this value to look up a field from an object, which then allows us to do the following:
setOptions((prevState: any) => ({
...prevState,
colors: [theme.palette.primary.main, theme.palette.primary[option700]],
// ...
});
Putting it all together, the entire code snippet is as follows:
type ObjectKey = keyof typeof theme.palette.primary;
const option700 = '700' as ObjectKey;
useEffect(() => {
setOptions((prevState: any) => ({
...prevState,
colors: [theme.palette.primary.main, theme.palette.primary[option700]],
// ...
});
// ...
});
We’re now able to access fields of an object using array notation just like in JavaScript. TypeScript just requires us to declare the index we’re using to be a key into the given object. If you declare a key that doesn’t exist, you’ll get a runtime error indicating that the key could not be found.
Conclusion
While I’m not necessarily the biggest fan of using array notation to access object properties, it’s something that I’ve run into on JavaScript projects I’ve worked on, and when converting those projects to TypeScript, it’s been useful to understand how to use that same notation in TypeScript since it’s not always possible to update the types to access fields directly (at least not without a lot of refactoring). When I have my choice, and it’s an easy change to make, I will use traditional notation to access a field (i.e.: obj.field), but this is handy to understand in cases where those changes are not straightforward.