吐槽幾句
typescript最大的賣點對於我來說就是型別檢查和IDE提示的快感了,以前我是抗拒用ts的,因為感覺它加入了太多東西了,又要新學很多東西,但是呢現在貌似ts是個大勢所趨,我最喜歡的框架vue都要用ts重構了,so,向ts前進吧!
我用rn開發了一個專案後,就迫不及待的準備在下個專案中開始介入ts了,但是完事開頭難,遇到了好多問題,主要在配置上...我自己想了辦法解決,但是感覺不完美,希望掘金ts大佬指導下,另外react-native的坑在上個專案也讓我見識了,不是一般的多,怪不得現在還沒釋出1.0版本,但是也沒辦法,跨端專案本身就及其負責,有時間總結下rn的坑.
開始
初始化react-native按照官網的教程,自己踩坑哈,接下來成功執行後,開始改造成ts,教程按照微軟的這個教程 TypeScript-React-Native-Starter
完成後出現了兩個我暫時解決的問題
NO1:
react-native中有個全域性的global物件,類似web中的window,有時候我會想往global上放一個全域性的方法或者變數,怎麼做呢?
我安裝的@types/react-native
是0.57.0版本,然後我再程式碼中輸入
global.time=33
這時候編譯器總是提示Error:(25, 3) TS2304: Cannot find name 'global'.
wfk? 疑問來了,我點開@types/react-native/index.d.ts明明看到了
...
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 的isseus收到了回覆,效率還可以哈
回覆就是
It isn't a good practice to use this global keyword, but it exists and should be present in react-native context.
嗯不是最佳實踐,但是有時候真的需要啊就像window物件,有時候還是需要掛在東西給它的,然後我們在原始碼也可以看到他們新增了global
那上面的問題就看他們什麼時候釋出新程式碼了,不過也算學習了。另外說個我的疑問 原始碼中是用
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:
我看到微軟那個教程上寫樣式是這麼寫的
// 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
,這裡有兩個問題要解決
- 解決ts識別路徑別名問題
- 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提示了,接著說那個問題,我在這個工具的文件上發現了個說明
"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,夜深了,晚安!