react-native and typescript 的一个style问题

react-native and typescript

以下react-native的代码,将样式都提取出来使用StyleSheet.create创建的话是这样:

import * as React from 'react';
import { AppRegistry, View ,StyleSheet} from 'react-native';

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'space-between',
    backgroundColor: '#F5FCFF',
  }
});

class AlignItemsBasics extends React.Component{
  render() {
    return (
      <View style={styles.container}></View>
    );
  }
};

AppRegistry.registerComponent('AwesomeProject', () => AlignItemsBasics);

这在.js环境中是没有问题,但是要加入typescript就会有点小问题了。使用的@types版本为:

"@types/react": "^15.0.16",
"@types/react-native": "^0.42.5",

现在先用typescript重写:

import * as React from 'react';
import { AppRegistry, View ,StyleSheet} from 'react-native';

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'space-between',
    backgroundColor: '#F5FCFF',
  }
});

class AlignItemsBasics extends React.Component<any , any>{
  render() {
    return (
      <View style={styles.container}></View>
    );
  }
};

AppRegistry.registerComponent('AwesomeProject', () => AlignItemsBasics);

这个时候会报:
Type '{ flex: number; flexDirection: string; justifyContent: string; backgroundColor: string; }' is not assignable to type 'ViewStyle'.
styles.container的type跟ViewStyle不匹配。有兴趣的可以去@type/react-native里看下ViewStyle的定义。这里说结论是,问题是出在flexDirection和justifyContent中这两个属性中,这两个属性是使用String Literal Types定义的。然后TS中像这样使用是识别不出来的:

interface Test {
  a: "p" | "q"
}
let x : Test;
let y = {
  a: "p"
}
x = y;//Type '{ a: string; }' is not assignable to type 'Test'

然后要解决这个问题可以断言:

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'space-between',
    backgroundColor: '#F5FCFF',
  } as ViewStyle
});

更好的方法是用范型声明style的类型:

import * as React from 'react'
import {View , Text , StyleSheet,ViewStyle ,TextStyle} from 'react-native'

export default function setup(){
  return class SampleTS extends React.Component<any,any> {
    render() {
      return (
        <View style={styles.container}>
          <Text>Hello world</Text>
        </View>
      );
    }
  }
}

interface Style {
  container: ViewStyle,
  welcome: TextStyle
}

const styles = StyleSheet.create<Style>({
  container: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'space-between',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  }
});

posted @ 2017-03-13 12:13  linyongkangm  阅读(2434)  评论(0编辑  收藏  举报