Jamie
Jamie

Reputation: 2081

Interface to extend or function to create similar types

I have API data that has a similar structure and I'd like to condense my code to have a it filter through a function. However, I am fairly new to typescript. I can't seem to get it correct with a function and I'm not sure how I would set this up using an interface. Essentially I would like to do:

Manually it would look like:

type DataType1 = {
  data: {
    stats: {
      first: string;
      last: string;
      email: string;
      password: string;
    };
  };
}

type DataType2 = {
  data: {
    stats: {
      username: string;
    };
  };
}

type DataType3 = {
  data: {
    stats: {
      status: string;
      createdAt: Date;
      orders: number;
    };
  };
}

...

What I would like it to be:

function setDataStructure(children: {}) {
  return {
    data: {
      stats: {
       ...children
      }
    }
  }
}

type DataType = setDataStructure({ 
  id: string;
  name: string;
});

Upvotes: 0

Views: 32

Answers (1)

Marty
Marty

Reputation: 39456

You can use a combination of intersection types and generics to clean up what you're trying to do.

For example, you could declare your base type:

type RootType<S> = {
  data: {
    stats: S;
  }
}

Here we have a data structure where a nested field stats is generic, so you could make a new type where stats has some new fields like this:

type Stats = {
  first: string;
  last: string;
  email: string;
  password: string;
}

type DataType = RootType<Stats>; 

Here DataType is equivalent to:

{
  data: {
    stats: {
      first: string;
      last: string;
      email: string;
      password: string;
    };
  };
}

Using intersection, you can extend an existing type to add additional fields - so if you wanted to add a single new field to the above, you could simply do:

type AdditionalStats = {
  username: string;
}

type ExtendedDataType = RootType<Stats & AdditionalStats>;

Which would be equivalent to:

{
  data: {
    stats: {
      first: string;
      last: string;
      email: string;
      password: string;
      username: string; // new username field added
    };
  };
}

Upvotes: 1

Related Questions