Dupocas
Dupocas

Reputation: 21317

Is it possible to declare a dynamic interface?

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

Answers (2)

Danilo Fuchs
Danilo Fuchs

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

Abido
Abido

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

Related Questions