1

To sum up my problem, I have an interface, User with an 'attributes' object filled with properties. I have another interface SpecialUser in which the 'attributes' object needs to contain properties that are not present on User. Currently, the new attributes object is overwriting the old one. I can get it to work by pasting in all properties from the parent interface and then appending the later ones, but that's not the most ideal solution.

export interface User{
  attributes: {
     full_name: string;
  }
}

export interface SpecialUser extends User {
  attributes: {
     occupation: string;
  }
}

What I want is for SpecialUser's 'attributes' to contain the fields on User's 'attributes' in addition to its new properties (so it would contain both full_name and occupation). The actual result is complete overwrite.

3 Answers 3

3

One option is to use an intersection type.

interface User {
  attributes: {
    full_name: string;
  };
}

type SpecialUser = {
  attributes: {
    occupation: string;
  };
} & User;

const user: SpecialUser = {
  attributes: {
    occupation: "job",
    full_name: "name"
  }
};

TypeScript Playground

Sign up to request clarification or add additional context in comments.

1 Comment

This is called an intersection type not union type.
0

Had the exact same problem, but wanted to keep it as interfaces and not types. This is similar to skovy's answer and only moves the intersection into the interface:

interface User {
  attributes: {
    full_name: string;
  };
}

interface SpecialUser extends User {
  attributes: {
    occupation: string;
  } & User["attributes"];
};

const user: SpecialUser = {
  attributes: {
    occupation: "job",
    full_name: "name"
  }
};

TypeScript Playground

Comments

0

Would something like this fit your use case?

export interface User{
  attributes: {
     full_name?: string;
     occupation?: string;
  }
}

or since you're really modifying the attributes

export interface Attributes{
    full_name: string;
}

export interface SpecialAttributes extends Attributes {
    //has all other properties of original attributes (i.e. full_name)
    occupation: string;
}

export interface User{
    attributes: Attributes
}

export interface SpecialUser extends User {
    attributes: SpecialAttributes //overrides original attributes
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.