Leo Jiang
Leo Jiang

Reputation: 26085

TypeScript saying a string is invalid even though it's in the union?

I copied the following from the AWS Amplify tutorial:

const styles = {
  container: { flexDirection: 'column' },
  ...
};

<div style={styles.container}>

But I'm getting:

Type '{ flexDirection: string; }' is not assignable to type 'CSSProperties'.
  Types of property 'flexDirection' are incompatible.
    Type 'string' is not assignable to type '"column" | "inherit" | "-moz-initial" | "initial" | "revert" | "unset" | "column-reverse" | "row" | "row-reverse" | undefined'.

I can easily work around this by placing the style inline, but I'm curious why TypeScript is considering this an error. This is a pretty basic example and I'm surprised TS is failing on it, so it makes me wary about using TS.

Upvotes: 16

Views: 8145

Answers (5)

Hasan Vajdi
Hasan Vajdi

Reputation: 130

It works for me with this code :

let labelPosition  = {
    display: "flex",
    flexDirection: "row",
}

<div style={labelPosition as React.CSSProperties}>

Upvotes: 0

Islam Murtazaev
Islam Murtazaev

Reputation: 1778

In my case putting as const on the object that was causing this problem helped to fix it.

// some function
return {
  label: {
    cursor: "pointer",
    display: "flex",
    width: "100%",
    flexDirection: "row",
  }
} as const

Upvotes: 2

Ramsses
Ramsses

Reputation: 21

import and use the type:

import type { Property } from 'csstype'

Use Property.FlexDirection to specify the type

Upvotes: 2

TLadd
TLadd

Reputation: 6884

Here is a TS Playground illustrating the problem and four possible solutions:

type FlexDirection = "column" | "inherit" | "-moz-initial" | "initial" | "revert" | "unset" | "column-reverse" | "row" | "row-reverse" | undefined;

type Styles = {
    container: {
        flexDirection: FlexDirection
    }
}

function doStuff(a: Styles) { }

const stylesDoesNotWork = {
    container: { flexDirection: 'column' }
};

const stylesWithCast = {
  container: { flexDirection: 'column' as 'column' }
}

const stylesFieldConst = {
    container: { flexDirection: 'column' } as const
};

const stylesConst = {
    container: { flexDirection: 'column' }
} as const;

doStuff(stylesDoesNotWork);
doStuff(stylesWithCast);
doStuff(stylesFieldConst);
doStuff(stylesConst);

By default, TypeScript is going to infer a type string for the object you are declaring. You might be mutating it somewhere and changing the value, in which case the literal type would not be correct. So the basic options to fix it are to:

  • Manually annotate the variable so TypeScript doesn't infer string.
  • Add as 'column' cast to tell TypeScript to use the literal type.
  • Use as const on either the field or entire object to tell TypeScript that field is not allowed to be changed, which allows Typescript to infer the literal value.

Upvotes: 22

pachonjcl
pachonjcl

Reputation: 741

Try this

const styles: { container: React.CSSProperties} = {
    container: { flexDirection: 'column' }
};

Upvotes: 2

Related Questions