skip to Main Content

Using parameter destructuring with null coalescing, typescript is having a issue with the optional name attribute. I do not want to change the original code to const name = data?.resource?.name ?? [] which probably would make typescript happy. How can I change the typescript so it would handle the parameter destructuring with null coalescing?

code

    private _getName(data: Data) {
    const { name } = data.resource ?? [];

type:

  type Data = {
    fullUrl?: string,
    resource?: {
      active?: boolean,
      address?: Address[],
      birthDate?: string,
      gender?: string,
      id?: string,
      identifier?: Indentifier[],
      materialStatus?: Coding[],
      meta?: Security[],
      name?: Name[],
      resourceType?: string,
      telecom?: Telecom[],
    },
    search?: {
      extension?: Extension[],
      mode?: string,
      score: number,
    }
  };
error:
 error TS2339: Property 'name' does not exist on type '{ active?: boolean; address?: Address[]; birthDate?: string; gender?: string; id?: string; identifier?: Indentifier[]; materialStatus?: Coding[]; meta?: Security[]; name?: Name[]; resourceType?: string; telecom?: Telecom[]; } | undefined[]'.

73     const { name } = data.resource ?? []

2

Answers


  1. This:

    const data: { resource?: { name?: string } } = {}
    const name = data?.resource?.name ?? []
    console.log(name) // []
    

    And this:

    const data: { resource?: { name?: string } } = {}
    const { name } = data.resource ?? []; // type error
    console.log(name) // undefined
    

    Are not logically equivalent.

    The first one resolves to an array when data.resource is undefined. So const name is assigned a value of [].

    The second one expects whatever is on the right hand side of the = to have a name property, and the value of that name property will be assigned to const name.

    But an array does not have a name property, so you get a type error, and at runtime would be undefined.


    In order to make this work with destructuring you must make sure whatever is on the right side here has a name property.

    For example:

    const { name } = data.resource ?? { name: [] };
    

    But that’s pretty silly.

    I think that this:

    const name = data?.resource?.name ?? []
    

    Is the cleanest solution here. It’s not advisable to use destructuring assignment unless all possible values being destructured support the property being destructured.

    See Typescript Playground. Click "Run" and see the console output for yourself.

    Login or Signup to reply.
  2. type Data = {
      fullUrl?: string;
      resource?: {
        active?: boolean;
        address?: Address[];
        birthDate?: string;
        gender?: string;
        id?: string;
        identifier?: Indentifier[];
        materialStatus?: Coding[];
        meta?: Security[];
        name?: Name[];
        resourceType?: string;
        telecom?: Telecom[];
      } | undefined; // Make the resource property optional explicitly
      search?: {
        extension?: Extension[];
        mode?: string;
        score: number;
      };
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search