1

I am iterating through a list of header names and I want to change the CSS style of the react component if the name matches one of three conditions. Currently, I have only made this work if it matches the first value but I haven't been able to make it work using a function call.

// works for one of the three conditions
  return (
    <TableHead>
      <TableRow>
        {headCells.map((headCell) => (
          < TableCell
            key={headCell.id}
            style={headCell.id === 'name' ? { position: 'sticky', left: 55, backgroundColor: 'white' } : {}}
          >

I tried to call a function to return the relevant style:

// 3 conditions
function setHeaderStyle(header: String) {
  if (header === 'name') {
    return { position: 'sticky', left: 55, backgroundColor: 'white' }
  } else if (header === 'totalZ') {
    return { position: 'sticky', right: 0, backgroundColor: 'white' }
  } else {
    return {}
  }
}

// calling above function to style based one 1/3 conditions
{headCells.map((headCell) => (
          < TableCell
            key={headCell.id}
            style={setHeaderStyle(headCell.id)}
          >

The above function causes the following error:

TS2322: Type '{ position: string; left: number; backgroundColor: string; right?: undefined; } | { position: string; right: number; backgroundColor: string; left?: undefined; } | { position?: undefined; left?: undefined; backgroundColor?: undefined; right?: undefined; }' is not assignable to type 'CSSProperties | undefined'.
  Type '{ position: string; left: number; backgroundColor: string; right?: undefined; }' is not assignable to type 'Properties<string | number, string & {}>'.
    Types of property 'position' are incompatible.
      Type 'string' is not assignable to type 'Position | undefined'.
  > 228 |             style={setHeaderStyle(headCell.id)}
        |             ^^^^^
Coderama
  • 11,050
  • 12
  • 44
  • 58
  • 1
    That's because `position` in your function is a `string`, but the `Properties` type expects it to be a valid CSS value. Also, please don't use `String` as a type. Use `string` in lowercase. See [this](https://stackoverflow.com/questions/14727044/what-is-the-difference-between-types-string-and-string) question for why. – kelsny Sep 16 '22 at 22:47

1 Answers1

2

As my comment describes, you have to make the return type of getHeaderStyle more specific. One method to achieve that is to use a const assertion:

function getHeaderStyle(header: string) {
  if (header === 'name') {
    return { position: 'sticky', left: 55, backgroundColor: 'white' } as const
  } else if (header === 'totalZ') {
    return { position: 'sticky', right: 0, backgroundColor: 'white' } as const
  } else {
    return {}
  }
}

Playground

kelsny
  • 23,009
  • 3
  • 19
  • 48
  • 1
    I would suggest to get read of the `as const` assertion and define the returned type from the function as `CSSProperties` in order to keep it more typed-safe. e.g. : `function getStyle(header: string): CSSProperties` – Yarin Barnes Sep 17 '22 at 01:26
  • Thanks @YarinBarnes, your suggestion made @caTS solution cleaner, although I did need to use `React.CSSProperties` instead of your recommended `CSSProperties` – Coderama Sep 17 '22 at 13:20