24

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]?

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
Jamie Hutber
  • 26,790
  • 46
  • 179
  • 291

1 Answers1

15

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') 
hawks
  • 861
  • 1
  • 8
  • 20