3

Suppose I can have objects like this:

const filters = {
    name: { value: 'some-value', rank: 'some-value' },
    place: { value: 'some-value', population: 'some-value' },
}

and it could also be like this...

const filters = {
    name: { value: 'some-value', rank: 'some-value' },
    place: { value: 'some-value', population: 'some-value' },
    description: { value: 'some-value', translation: 'some-value' },
    popularity: { value: 'some-value', ranking: 'some-value' },
}

How do I create an interface for that (a dynamic object)?

1
  • 3
    Does this answer your question ? Commented May 5, 2022 at 8:15

2 Answers 2

0

One possibility would be to make description and popularity optional by adding a ?, like so:

Approach 1

interface Filters {
    name: object,
    place: object,
    description?: object,
    popularity?: object,
}

For more information on property modifiers, see the documentation

Another approach would be to use interface inheritance by using the keyword extends

Approach 2

interface ParentFilters {
    name: object,
    place: object
}

And for the derived interface

interface derivedFilters extends parentFilter {
   description: object,
   popularity: object,
}
Sign up to request clarification or add additional context in comments.

Comments

0

It's not possible to create a type which forces to be { a } or { a, b, c }. This is called Discriminated Unions and you can read more about this problem here.

You can use booth approaches which @SimonRosengren mentioned. To force typesafety when defining an object you have to implicitly say which type is what:

interface FilterTypeBase {
    name: { value: string, rank: string },
    place: { value: string, population: string }
}

interface FilterTypeExtended extends FilterTypeBase {
    description: { value: string, translation: string },
    popularity: { value: string, ranking: string }
}

// 👍 OK
const filters: FilterTypeBase = {
    name: { value: 'some-value', rank: 'some-value' },
    place: { value: 'some-value', population: 'some-value' },
}

// ❌ ERROR: Property 'popularity' is missing
const filters2: FilterTypeExtended = {
    name: { value: 'some-value', rank: 'some-value' },
    place: { value: 'some-value', population: 'some-value' },
    description:  { value: "string", translation: "string" }
}

If you use want to decide in a function which of booth variantes your type is. You can do this with narrowing:

type FilterType = FilterTypeBase | FilterTypeExtended 

function doSomething(filter: FilterType) {
    if('description' in filter) {
        // Here it's the extended type
    }
}

Typescript docs: Narrowing

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.