Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Typescript return union "either or" throws property not found error

I’m trying to write a Typescript helper function that returns a valid either/or type but I’m not understanding how to appease the compiler. My types are defined as follows:

export interface MediaElementUrl {
  media_type: 'image' | 'video';
  url: string;
  attachment_id: never;
  buttons?: Button[];
}

export interface MediaElementAttachmentId {
  media_type: 'image' | 'video';
  url: never;
  attachment_id: string;
  buttons?: Button[];
}

export type MediaElement = MediaElementUrl | MediaElementAttachmentId;

You can have a MediaElement that has a url or a attachment_id but not both. My helper class is as follows:

export class MediaElementComponent {
  protected constructor(
    public media_type: 'image' | 'video',
    public button: Button,
    public attachment_id?: string,
    public url?: string
  ) {}

  public validate(): void {
    if (this.attachment_id && this.url) throw new Error('Cannot set url and attachment_id');
  }

  public get(): MediaElement {
    if (this.attachment_id) {
      return {
        buttons: [this.button],
        media_type: this.media_type,
        attachment_id: this.attachment_id!,
      };
    }
    return {
      buttons: [this.button],
      media_type: this.media_type,
      url: this.url!,
    };
  }
}

The compiler is throwing an error on the return from get()

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

TS2322: Type '{ buttons: Button[]; media_type: "image" | "video"; attachment_id: string; }' is not assignable to type 'MediaElement'.   Property 'url' is missing in type '{ buttons: Button[]; media_type: "image" | "video"; attachment_id: string; }' but required in type 'MediaElementAttachmentId'.

Can anyone help me understand where I’m going wrong? Thanks

>Solution :

Simple fix: You need to make the forbidden properties optional:

export interface MediaElementUrl {
  media_type: 'image' | 'video';
  url: string;
  attachment_id?: never;
  buttons?: Button[];
}

export interface MediaElementAttachmentId {
  media_type: 'image' | 'video';
  url?: never;
  attachment_id: string;
  buttons?: Button[];
}

Otherwise TypeScript will enforce that these properties are present with a type of never, which is impossible.

Playground

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading