Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 277
Leo Jiang Avatar asked Dec 29 '25 14:12

Leo Jiang


2 Answers

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.
like image 93
TLadd Avatar answered Jan 01 '26 03:01

TLadd


Try this

const styles: { container: React.CSSProperties} = {
    container: { flexDirection: 'column' }
};
like image 21
pachonjcl Avatar answered Jan 01 '26 04:01

pachonjcl