使用typescript开发react-native前期踩坑记录

吐槽几句

typescript最大的卖点对于我来讲就是类型检查和IDE提示的快感了,之前我是抗拒用ts的,由于感受它加入了太多东西了,又要新学不少东西,可是呢如今貌似ts是个大势所趋,我最喜欢的框架vue都要用ts重构了,so,向ts前进吧!javascript

我用rn开发了一个项目后,就火烧眉毛的准备在下个项目中开始介入ts了,可是完事开头难,遇到了好多问题,主要在配置上...我本身想了办法解决,可是感受不完美,但愿掘金ts大佬指导下,另外react-native的坑在上个项目也让我见识了,不是通常的多,怪不得如今还没发布1.0版本,可是也没办法,跨端项目自己就及其负责,有时间总结下rn的坑.html

开始

初始化react-native按照官网的教程,本身踩坑哈,接下来成功运行后,开始改形成ts,教程按照微软的这个教程
TypeScript-React-Native-Startervue

完成后出现了两个我暂时解决的问题java

NO1:

react-native中有个全局的global对象,相似web中的window,有时候我会想往global上放一个全局的方法或者变量,怎么作呢?react

我安装的@types/react-native是0.57.0版本,而后我再代码中输入
`
global.time=33
`
这时候编译器老是提示Error:(25, 3) TS2304: Cannot find name 'global'. wfk? 疑问来了,我点开@types/react-native/index.d.ts明明看到了git

...
declare global {
    function require(name: string): any;
    }
...

这个问题搞了我很久了,github 一开始我觉得是bug就去github搜搜issues发现没有,因而提了个issues,但愿有回应,可是得想个办法解决:
首先在 本身的src目录新建一个文件夹typings,用来放本身的类型声明文件新建一个global.d.ts,名字随便起,我以前以为是只能叫这个,而后在里面写以下代码程序员

declare module global{
    let name:string;
    let time:Time;
    let dp:(px:number)=>number;
    let font:(px:number)=>number;
}

而后就能够在代码中使用了,看图github

喜大普奔,就在我写文章的时候,github 的isseus收到了回复,效率还能够哈

回复就是 web

It isn't a good practice to use this global keyword, but it exists and should be present in react-native context.
嗯不是最佳实践,可是有时候真的须要啊就像window对象,有时候仍是须要挂在东西给它的,而后咱们在源码也能够看到他们添加了globaltypescript

那上面的问题就看他们何时发布新代码了,不过也算学习了。另外说个个人疑问
源码中是用

declare global{
     function require(name: string): any;

    /**
     * Console polyfill
     * @see https://facebook.github.io/react-native/docs/javascript-environment.html#polyfills
     */
    interface Console {
        error(message?: any, ...optionalParams: any[]): void;
        info(message?: any, ...optionalParams: any[]): void;
        log(message?: any, ...optionalParams: any[]): void;
        warn(message?: any, ...optionalParams: any[]): void;
        trace(message?: any, ...optionalParams: any[]): void;
        debug(message?: any, ...optionalParams: any[]): void;
        table(...data: any[]): void;
        disableYellowBox: boolean;
        ignoredYellowBox: string[];
    }
}

直接declare global是什么意思?通常不都是declare namespace ,declare module,declare function等等么

NO2:

2018.10.29更新,我在githut issues看到了这个问题 他们讨论结果貌似是这是一个bug?可能会在ts3.2修复?
请自行看一下
https://github.com/DefinitelyTyped/DefinitelyTyped/issues/29265

我看到微软那个教程上写样式是这么写的

// styles

const styles = StyleSheet.create({
  root: {
    alignItems: "center",
    alignSelf: "center"
  }
})

嗯完美,没问题,但是我本身写个就报错了

// styles
const styles = StyleSheet.create({
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 0,
  }
});
Error:(42, 11) TS2322: Type 'RegisteredStyle<{ fontSize: number; textAlign: string; margin: number; }>' is not assignable to type 'StyleProp<TextStyle>'.
  Type 'RegisteredStyle<{ fontSize: number; textAlign: string; margin: number; }>' is not assignable to type 'RecursiveArray<false | TextStyle | RegisteredStyle<TextStyle>>'.
    Property 'length' is missing in type 'Number & { __registeredStyleBrand: { fontSize: number; textAlign: string; margin: number; }; }'.

意思就是类型不对,解决办法

type Style={welcome:TextStyle}// 定义一个别名
// styles
const styles = StyleSheet.create<Style>({
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 0,
  }
});

可是这样写好麻烦啊,并且我参考的文章别人都没有在这里传入类型,后来翻了翻github 貌似有人说这是新版本才有这个问题的,因此我还不知作别人怎么解决的,我先这么写吧,
我想能不能定义一个全局的Style别名或者接口呢?每一个页面直接用就行了
一样的我在global.d.ts这么写

import {ViewStyle} from "react-native";

interface Style{
    [prop:string]:ViewStyle
}

这么一写不知道为何没法识别global这个变量了,提示找不到,我把导入语句删了就没事了这是为何?真的须要大佬帮忙解释了。

NO3:

怎么写路径别名?
我在百度一顿搜索,好吧,还真的有 babel-plugin-root-import ,这里有两个问题要解决

  1. 解决ts识别路径别名问题
  2. ts编译时识别了还得让运行时的也能识别,也就是让babel转换别名

奔着这个思路,我两个都配置好了,发现始终没法让babel识别,老是报错找到不到模块
配置大概这样子

// .babelrc
{

  "env": {
    "production": {
      "plugins": [
        "transform-remove-console",[
          "babel-plugin-root-import",
          {
            "paths":[
              {
                "rootPathSuffix": "src",
                "rootPathPrefix": "@src"
              },
              {
                "rootPathSuffix": "./src/components",
                "rootPathPrefix": "@components"
              }
            ]
          }
        ]
      ]
    }
  },
  "presets": ["module:metro-react-native-babel-preset"],
  "plugins": [[
    "babel-plugin-root-import",
    {
      "paths":[
        {
          "rootPathSuffix": "src",
          "rootPathPrefix": "@src"
        },
        {
          "rootPathSuffix": "./src/components",
          "rootPathPrefix": "@components"
        }
      ]
    }
  ]]
}

我这个配置我感受没错,按照插件文档写的如出一辙,可是依旧不行,难道我写错了吗?
不过最终我放弃了,由于我最新版本的react-native已经使用了一个叫react-native-typescript-transformer的工具在编译时自动转换ts为js,从前听说用ts写rn要先用ts编译器转换成js,而后再让rn 读取转换后的代码,这个开发体验很很差啊,如今有了这个,不用再单独去转js了,不过我以为有个很差的,就是它只转换ts不检查类型错误,也就是你类型不对照样能运行,关于这个github也有讨论,我大概看过,貌似意思是故意而为之,我仍是但愿直接报错,别运行,如今只能借助ide提示了,接着说那个问题,我在这个工具的文档上发现了个说明


刚开始没认真看啊,毕竟英语,后来仔细看了看原来是用这个工具能够配置别名,可是方法有点奇怪
大概意思是在你想要起别名的文件夹里面新建一个package.json文件,里面写个name属性叫你配置的别名,这个别名要跟tsconfig配置的一直
好比我在tsconfig配置个路径别名

"baseUrl": ".",   //注意这个必定要配置,否则paths没用              
"paths": {
     "@components/*":["src/components/*"]
},

接下来我要在components文件夹新建一个package.json

{
  "name":"@components"
}

这样再运行,终于跑起来了,同时ts能识别了,厉害的是ws也能跳转了,以前在vue中配置别名,ws是不识别的

最后

我会持续更新这个文章,保持踩坑,但愿有大佬看到我上面的问题来评论交流下啊,另外接触react-native后我深入的感觉到github issues的强大和英语能力的需求,我遇到的rn的坑大部分我只须要把报错在rn的issues一搜索就能搜到,可是都是英语,因此程序员真的须要提升英语阅读能力哦,最后再说句,rn的新版本不要当即用,100%有坑,若是能力强能够先踩坑,另外遇到问题了,不要怂,提issues,用有道词典翻译一下大体就能说明白了,个人好几个问题都是提issues解决的最后。emmm,夜深了,晚安!

相关文章
相关标签/搜索