Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript optional chaining dynamic property

I am trying to access a dynamic property with safety provided by optional chaining that is available in TS. However it appears that this is not valid.

export const theme = {
  headers: {
    h1: {
    },
    h6: {
      color: '#828286'
    },
  },
}
console.info(theme?.headers?.['h6']?.color ?? '#000') //will pass
console.info(theme?.headers?.['h1']?.color ?? '#000') //will fail

Error

Identifier expected.  TS1003

    10 |   const StyledTypography = styled.div`
    11 |     margin: 0;
  > 12 |     color: #000; ${({theme}) => theme?.headers?.[variant]?.color ?? '#000'}
       |                                                ^
    13 |   `
    14 |   return (
    15 |     <StyledTypography as={variant}>

It appears that the optional changing will apply to the optional [] as a type but not to the values inside.

How can I make this optional without having to do [undefined || someDefaultValue]?

like image 577
Jamie Hutber Avatar asked Jan 10 '20 13:01

Jamie Hutber


People also ask

Does JavaScript support optional chaining?

Introduction to the JavaScript optional chaining operator allows you to access the value of a property located deep within a chain of objects without explicitly checking if each reference in the chain is null or undefined .

What is JavaScript optional chaining?

The optional chaining operator ( ?. ) enables you to read the value of a property located deep within a chain of connected objects without having to check that each reference in the chain is valid.

Is optional chaining safe?

Optional chaining is a safe and concise way to perform access checks for nested object properties.

Does optional chaining work on null?

Conclusion. The optional chaining operator is ideal for null-checking deeply nested objects. It allows us to avoid writing a whole bunch of if statements, nested, to check for the existence of the properties.


1 Answers

You can create an interface that maps your theme object and pass the compiler type checking.

interface Headers {
    [key: string]: {
        [key: string]: string
    }
}

interface Theme {
    headers: Headers
}

const theme: Theme = {
  headers: {
    h1: {
    },
    h6: {
      color: '#828286'
    },
  },
}
console.info(theme?.headers?.['h6']?.color ?? '#000') //will pass
console.info(theme?.headers?.['h1']?.color ?? '#000') 
like image 112
hawks Avatar answered Oct 13 '22 15:10

hawks