Ralph
Ralph

Reputation: 32304

TypeScript type inference issue with string literal

In a react-native application, I have the style

const styles = StyleSheet.create({
    text: {
        textAlign: "center"
    },
})

used in <Text style={styles.text} />, but the tsc compiler gives the following error:

Types of property 'textAlign' are incompatible.
Type 'string' is not assignable to type '"center" | "auto" | "left" | "right"'.

The definition of TextStyle in @types/react-native includes:

export interface TextStyle extends TextStyleIOS, TextStyleAndroid, 
ViewStyle {
    // ...
    textAlign?: "auto" | "left" | "right" | "center"
    // ...
}

Why is the compiler complaining about incompatibility? It seems that it is inferring the type of textAlign to be the too general string instead of checking the actual value ("center").

I know that I can use a as TextStyle to avoid the problem, but I would like to know why it is happening and if I should file a ticket against the compiler.

Upvotes: 15

Views: 17649

Answers (4)

Greg
Greg

Reputation: 2600

I wanted to do similiar in React TypeScript and the answers here are close but were not quite the working solution. Instead I found I had to import Property from csstype, and then cast as Property.TextAlign.

In the below Example I call to a function that returns Property.TextAlign instead of a regular string.

import { Property } from 'csstype'

...

const getTextAlign = (dataType: string):Property.TextAlign => {
    var output:string = "left";

    if(dataType === "Money"){
        output = "right";
    }

    return output as Property.TextAlign;
}

...

<td style={{textAlign: getTextAlign(this.state.dataType) }}>

Trying to follow the other solutions, I just got an error that TextAlignProperty wasn't defined in csstype. Here I was particularly working in a PCF control, but that shouldn't matter. This may be a difference due to version of React.

Upvotes: 3

OM Bharatiya
OM Bharatiya

Reputation: 2170

If you're using Typescript 3.4+ you can make use of the as const notation:

export const locationInput = {
  textAlign: 'center' as const
};

For more info check documentations here.

Upvotes: 27

Gerhat
Gerhat

Reputation: 821

Another option whould be:

import { TextAlignProperty } from 'csstype'

const styles = StyleSheet.create({
    text: {
        textAlign: "center" as TextAlignProperty
    },
})

Upvotes: 6

libertyernie
libertyernie

Reputation: 2684

This ought to work:

const styles = StyleSheet.create({
    text: {
        textAlign: "center" as "center"
    },
})

Normally TypeScript would type textAlign as string, but since it can't just be any string, you can cast it to the more specific type.

Upvotes: 24

Related Questions