Search code examples
typescriptecmascript-6undefinedobject-destructuring

Destructure an object that has the possibility of being undefined as a one-liner in a parameter list


Given an interface MyType:

interface MyType {
  options?: { field0: string, field1: string, field2: string };
}

Mapping over an array, myArray, which has type MyType[], one can destructure the options attribute like this:

myArray.map(({ options }) => {
 const { field0, field1, field2 } = options!;

Note the bang (!), because options could be undefined.

I was trying to turn this into a one-liner, like this:

myArray.map(({ options: { field0, field1, field2 }}) => {

But, this results in errors like "Property 'field0' does not exist on type 'MyType | undefined'" which makes sense because of the way options is typed.

Usually in this scenario I can add the bang operator to bypass the undefined check.

I tried:

myArray.map(({ options: { field0, field1, field2 }!}) => {

and:

myArray.map(({ options!: { field0, field1, field2 }}) => {

...but neither attempts are syntactically valid.

Is there a way to destructure an object that has the possibility of being undefined as a one-liner in a parameter list?


Solution

  • If you are sure that the array contains only objects with options, you can use a type assertion on the array itself:

    (myArray as Required<MyType>[]).map(({ options: { field0, field1, field2 }}) => {
    

    An alternative that lets you use the non-null assertion is mapping in two steps:

    myArray.map(el => el.options!).map({ field0, field1, field2 }) => {
    

    However, the proper safe way to handle this is to anticipate that some array elements actually might have no options, and default those to an empty object:

    myArray.map(({ options: { field0, field1, field2 } = {}}) => {