Élodie Petit
Élodie Petit

Reputation: 5914

Creating a weird type in TypeScript

How can I create a type that will represent the objects like the one below in TypeScript?

const definition = {
    'with_boolean_prop': {
        prop1: true
    },
    'with_object_prop': {
        prop2: {
            options: {}
        }
    }
    'with_multiple_props': {
        prop3: {
            options: {}
        }
        prop4: true
    }
};

Keys will be strings as in { [key: string]: any }. Anything can be used for the names prop1 and prop2. But their types must be boolean or an interface that only includes an options property.

This is what I have so far:

type ItemSchema = { options: string };
type Item = { [key: string]: Boolean | ItemSchema };
type Schema = { [key: string]: Item };

const schema: Schema = {
    'item1': {
        'prop1': true,
        'prop2': {
            options: 'some options'
        }
    }
};

Works but I can only use strings for the prop names, as the indexers in TypeScript can only be strings or numbers which is kind of limiting.

EDIT There's been some misunderstanding, probably because of my English :-) I'm not against using strings or numbers for indexers. What I'm trying to achieve is define a type whose properties can only be a set of predefined types.

Like this:

myObject = {
    aProperty: Can be Boolean | Object
    bProperty: Can be Boolean | Object
    xxxProperty: Can be Boolean | Object
    anyProperty: Can be Boolean | Object
}

If I use string indexers for the property names, than I can achieve what I want as you can see from the example above (ItemSchema and other types) because it's possible to use any value in a string indexer. If I try to do this without string keys, than I can't restrict the types that the property can accept.

Upvotes: 1

Views: 188

Answers (1)

Kewin Dousse
Kewin Dousse

Reputation: 4027

Your current solution is not far from what you're trying to achieve. If I understood correctly, the problem is that you would like to also use number as prop name instead of only string, right ?

If yes, then you can use & to create an Intersection type. Here's your example implementing this :

type ItemSchema = { options: string };
type Item = { [key: string]: Boolean | ItemSchema } & { [key: number]: Boolean | ItemSchema };
type Schema = { [key: string]: Item };

const schema: Schema = {
    'item1': {
        'prop1': true,
        'prop2': {
            options: 'some options'
        },
        4: true,
        5: {
            options: 'an other option'
        },
    }
};

Here is the TypeScript Playground of the code.

Upvotes: 1

Related Questions