Reputation: 21317
I'm currently translating my style solution based on jss
to typescript
and I've stumble in the following situation.
Consider my basic setup
import { useStyles } from './styles'
const styles = theme =>({
root : { color: 'white' },
foo : { backgroundColor: 'red' },
})
const Component = () =>{
const classes = useStyles(styles)
return <div className={classes.root} />
}
You pass a style's object to useStyles
and the returned value is an object which contains all keys declared inside styles
. So my classes
object looks like this
{
root : 'random-name123',
foo : 'random-name124'
}
Since I can't possibly know which keys styles
will have, my current interface for classes
is just a dictionary
interface Classes {
[index: string]: string
}
My question is:
Can I declare an interface
in such a way that all keys passed to styles
are declared as being part of Classes
? So that when I type classes.
I would be able to see all possible keys for classes
?
In other words, I want the keys which compose Classes
to be predictable. So that if I pass a styles
objects like this
{
foo : {/*...*/},
bar: {/*...*/}
}
My Classes
interface would look like
{
foo : string,
bar : string
}
Upvotes: 2
Views: 189
Reputation: 1051
In Typescript, you can use the Record
utility type to map a union of types to another type in a dictionary.
To get all keys of a defined object, you can use keyof typeof object
, which would give you "root" | "foo"
in your case.
So, if you want to map all keys to strings, use:
type Classes = Record<keyof typeof styles, string>
Upvotes: 1
Reputation: 802
I hope this is what you meant:
const styles = {
root: 'value1',
foo: 'value2'
};
type stylesType = typeof styles;
interface Classes extends stylesType {
[x: string]: string;
}
Now when an object is typed as Classes it will have the keys root
and foo
.
Inspired by Types from both keys and values of object in Typescript
Upvotes: 3