Definitelytyped: @types/react-native don't work with typescript 3.1.1

Created on 28 Sep 2018  Â·  16Comments  Â·  Source: DefinitelyTyped/DefinitelyTyped

  • [x] I tried using the latest stable version of tsc (typescript@latest = [email protected]). https://www.npmjs.com/package/typescript
  • [x] I tried using the @types/[email protected] package and had problems.
  • [x] [Mention](https://github.com/blog/821-mention-somebody-they-re-notified) the authors (see Definitions by: in index.d.ts) so they can respond.

    • Authors: @alloy, @huhuanming, @iRoachie, @skn0tt, @timwangdev, @kamal, @nelyousfi, @alexdunne, @swissmanu, @bm-software, @tkrotoff, @a-tarasyuk, @mvdam, @esemesek

Current typings produce very strange errors being used with typescript 3.1.1
I submit https://github.com/Microsoft/TypeScript/issues/27421 to typescript repo, but sure that DT also should track this issue. Main problem, that I can't create minimal example for this. And I can't personally understand why ts since 3.1 behave so strangely. It would be good if anyone can help with this.

Next is mostly duplication of info from https://github.com/Microsoft/TypeScript/issues/27421:

import React from 'react'
import { StyleSheet, Text } from 'react-native'

const s = StyleSheet.create({
  didNotWork: {
    fontSize: 16,
    fontWeight: '900', // if we comment this line, errors gone
    marginTop: 5, // if this line commented, errors also gone
  },
  work: {
    fontSize: 18,
//    fontWeight: '900', // when uncommented also work
  },
})

export const sample1 = <Text style={s.work} />
export const sample2 = <Text style={s.didNotWork} />
// ^ this line generate error:
// index.tsx:17:30 - error TS2322: Type 'RegisteredStyle<{ fontSize: number; fontWeight: string; marginTop: number; }>' is not assignable to type 'StyleProp<TextStyle>'.
//   Type 'RegisteredStyle<{ fontSize: number; fontWeight: string; marginTop: number; }>' is not assignable to type 'RecursiveArray<false | TextStyle | RegisteredStyle<TextStyle> | null | undefined>'.
//     Property 'length' is missing in type 'Number & { __registeredStyleBrand: { fontSize: number; fontWeight: string; marginTop: number; }; }'.
// 17 export const sample2 = <Text style={s.didNotWork} />
//                                 ~~~~~
//   node_modules/@types/react-native/index.d.ts:907:5
//     907     style?: StyleProp<TextStyle>;
//             ~~~~~
//     The expected type comes from property 'style' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<Text> & Readonly<{ children?: ReactNode; }> & Readonly<TextProps>'
export const sample3 = <Text style={{fontSize: 16, fontWeight: '900', marginTop: 5}} />

This sample shows the error. There is sandbox repo: https://github.com/vovkasm/rn-ts-3.1.1 (to reproduce, clone and npm install && npm test)

  1. If I comment out fontWeight or marginTop style of didNotWork key, error dissapeared
  2. If I add fontWeight to work key, error dissapeared

Why is this?

Most helpful comment

I'm currently working around this issue by casting. I feel doing this consistently will allow me to quickly find & replace to remove when it's addressed

<Image
      style={styles.closeButtonIcon as ImageStyle}
      source={require('resources/icons/png/x.png')}
/>

All 16 comments

Update from https://github.com/Microsoft/TypeScript/issues/27421: It seems that typescript team qualified this as a bug and assign it to typescript 3.2 milestone. So I hope this will be fixed in [email protected]

I'm currently working around this issue by casting. I feel doing this consistently will allow me to quickly find & replace to remove when it's addressed

<Image
      style={styles.closeButtonIcon as ImageStyle}
      source={require('resources/icons/png/x.png')}
/>

@mrnickel So you no more can detect errors in styles. For ex you add fontSize to styles.closeButtonIcon and now type system will not detect that error because cast to ImageStyle. This error will be discovered only in runtime.

Our workaround is to type the Styles object, which will give you errors when you use the wrong type, but you have to be explicit about all the style rules, which is tedious:

import { StyleSheet, TextStyle, ViewStyle } from "react-native";

type Style = {
    container: ViewStyle;
    title: TextStyle;
    icon: ImageStyle;
};

export default StyleSheet.create<Style>({
    container: {
        flex: 1
    },
    title: {
        color: red
    },
    icon: {
        width: 10,
        height: 10
    }
});

Um... yes this will work. But then you don't need StyleSheet at all, you can use simple constants - it has no benefits on runtime, and with this workaround it lost benefits to not specify types:

const containerStyle: ViewStyle = { flex: 1 }
const titleStyle: TextStyle = { color: 'red' }
const iconStyle: ImageStyle = { width: 10, height: 10 }

We also do what @sverrejoh mentioned for the same reasons. It’s not true that this means you don’t need to use StyleSheet.create(…), you use it for performance reasons, see https://facebook.github.io/react-native/docs/stylesheet

@alloy I understand what docs says, but can prove that code:

const myStyle: ViewStyle = { flex: 1 }
export const FlexView: React.SFC = (props) => <View style={myStyle}>{props.children}</View>

has almost same performance (even slightly faster) compared to

const s = StyleSheet.create({ flex: { flex: 1 } })
export const FlexView: React.SFC = (props) => <View style={s.flex}>{props.children}</View>

because if you look at sources, you discover that latest chunk effectively extracted to this (see: https://github.com/facebook/react-native/blob/0.57-stable/Libraries/StyleSheet/StyleSheet.js#L373):

const s = { flex: { flex: 1 } }
export const FlexView = (props) => <View style={s.flex}>{props.children}</View>

And yes, in previous versions of RN it was global registry of styles, but it was even more slow, because it never crossed bridge border actually (proof from 0.55 branch) 😀

@alloy seems like the docs are outdated. After landing https://github.com/facebook/react-native/commit/a8e3c7f5780516eb0297830632862484ad032c10 StyleSheet.create just returns the passed in object unaltered. The IDs used before are no more, ReactNativePropRegistry (StyleSheetRegistry) is gone.

Hah, yeah then it doesn’t make much sense 😆

Can someone make a pr to fix this based on this clarification ?

PR already here (but was closed by bot?): https://github.com/DefinitelyTyped/DefinitelyTyped/pull/29688

Update from Microsoft/TypeScript#27421: typescript team qualified this as working as intended, described the behavior and helped to discover potential solution. PR is here #29688

Which style should i use for the button component is it TextStyle or what style

Our workaround is to type the Styles object, which will give you errors when you use the wrong type, but you have to be explicit about all the style rules, which is tedious:

import { StyleSheet, TextStyle, ViewStyle } from "react-native";

type Style = {
    container: ViewStyle;
    title: TextStyle;
    icon: ImageStyle;
};

export default StyleSheet.create<Style>({
    container: {
        flex: 1
    },
    title: {
        color: red
    },
    icon: {
        width: 10,
        height: 10
    }
});

i do this,and Do you know why the compiler will tell me that I cannot find name global when I type global?
global.time=333
Error:(25, 3) TS2304: Cannot find name 'global'.
thank you!

Our workaround is to type the Styles object, which will give you errors when you use the wrong type, but you have to be explicit about all the style rules, which is tedious:

import { StyleSheet, TextStyle, ViewStyle } from "react-native";

type Style = {
    container: ViewStyle;
    title: TextStyle;
    icon: ImageStyle;
};

export default StyleSheet.create<Style>({
    container: {
        flex: 1
    },
    title: {
        color: red
    },
    icon: {
        width: 10,
        height: 10
    }
});

i do this,and Do you know why the compiler will tell me that I cannot find name global when I type global?
global.time=333
Error:(25, 3) TS2304: Cannot find name 'global'.
thank you!

this is a bug,and the author(@types/react-native) have add global variable

With this type of snippet it is still ending up in compile errors:

type Foo = {
    bar: RegisteredStyle<ImageStyle>;
};

const fooStyles: Foo = StyleSheet.create<StyleSheet.NamedStyles<Foo>>({
    bar: {
        width: undefined
    }
});
src/screens/WelcomeScreen.tsx:119:7 - error TS2322: Type '{ bar: RegisteredStyle<ViewStyle | TextStyle | ImageStyle>; }' is not assignable to type 'Foo'.
  Types of property 'bar' are incompatible.
    Type 'RegisteredStyle<ViewStyle | TextStyle | ImageStyle>' is not assignable to type 'RegisteredStyle<ImageStyle>'.
      Type 'RegisteredStyle<ViewStyle | TextStyle | ImageStyle>' is not assignable to type '{ __registeredStyleBrand: ImageStyle; }'.
        Types of property '__registeredStyleBrand' are incompatible.
          Type 'ViewStyle | TextStyle | ImageStyle' is not assignable to type 'ImageStyle'.
            Type 'ViewStyle' is not assignable to type 'ImageStyle'.
              Types of property 'overflow' are incompatible.
                Type '"hidden" | "visible" | "scroll" | undefined' is not assignable to type '"hidden" | "visible" | undefined'.
                  Type '"scroll"' is not assignable to type '"hidden" | "visible" | undefined'.

119 const fooStyles: Foo = StyleSheet.create<StyleSheet.NamedStyles<Foo>>({

Based on the error the issue that overflow is defined in FlexStyle and ImageStyle as well, but with different value set.

I think this could be a TypeScript issue, so I added a commend on the original TS issue.

https://github.com/Microsoft/TypeScript/issues/27421#issuecomment-439653891

Was this page helpful?
0 / 5 - 0 ratings