Getting error when trying to initialize nested array "The left-hand side of an assignment expression may not be an optional property access."

Viewed 618

I have an object whith an array and inside this a second array, just like this.

export class OrdenCompra {
public id?: number,
public insumos?: OrdenCompraInsumo[],
}

export class OrdenCompraInsumo {
id?: number;
traslados?: IImpuestoTraslado[];
}

export class ImpuestoTraslado{
public id?: number,
public impuesto?: number
}

i want to add some value to

traslados

like this

const retencion = new ImpuestoRetencion();
ordenCompra?.insumos[index]?.retenciones?.push(retencion); 

but at this point

ordenCompra?.insumos[index]?.retenciones?

it is

undefined

so the value it is never assigned.

if i try to initialize i get an error.

ordenCompra?.insumos[index]?.retenciones = []

or

ordenCompra?.insumos[index]?.retenciones = ImpuestoRetencion[];

or

ordenCompra?.insumos[index]?.retenciones: ImpuestoRetencion[] || [];

which says

The left-hand side of an assignment expression may not be an optional property access.

so i have not been able to assign a value to this array. i know this is a very trivial question but even when i have search for hours.

1 Answers

?., known as optional chaining is only useful for reading/invoking, not for setting. From the docs:

At its core, optional chaining lets us write code where TypeScript can immediately stop running some expressions if we run into a null or undefined.

So you might interpret const foobarbaz = foo?.bar?.baz like this:

// Will have type: undefined | typeof baz
const foobarbaz = foo === undefined || foo === null
                    ? undefined
                    : foo.bar === undefined || foo.bar === null
                      ? undefined
                      : foo.bar.baz

This makes no sense in the context of a set because you cannot set null or undefined to a value:

foo?.bar?.baz = foobarbaz
// ^^^^^^^^^^ - The left-hand side of an assignment expression may not be
//                an optional property access.

// Practically the same as:
(foo === undefined || foo === null
  ? undefined
  : foo.bar === undefined || foo.bar === null
    ? undefined
    : foo.bar.baz) = foobarbaz

To set this property, you must check that the value of foo.bar.baz is not nullish. This can be done by wrapping the assignment in an if statement:

foo.bar.baz = something; // error!

if(foo?.bar?.baz) {
  foo.bar.baz = something; // OK
}

If you know that your value isn't null or undefined but the compiler isn't able to determine this on its own, use the non-null assertion operator (!.):

foo!.bar!.baz = something; // OK

Here is a playground demonstrating each of these senarios.

Related