node+ts的心得與坑


首先先明確,用node+ts的目的,為什么不ng+ts。這一點后面還會反復提醒自己 node畢竟不是ng。

用node的理由:

處理js,在后端操縱dom,讀寫類html格式的東西,比直接用py的后端更舒服。

着眼點還是后端數據處理,作為類似單機版數據庫的后台進程db_master(RESTful API等於 數據庫的CRUD)。

不需要寫界面,不需要web component這些。所以用ts,不意味着,到處都是class。仍然是data居多,function居多。

用ts的理由:

主要理由:給了增加類型注解的選擇權,export方式也更貼近es6標准。

不太成立的理由:自己畢竟寫過了點ng。ts用着還可以,其實es6本身,經過2015 2016 2017,也很不錯了。

 

用node+ts稍微寫點東西,就發現

1 各種庫必須自己知道選擇,安裝。

2 js語言太亂。編碼風格,module居然好幾套玩法,瀏覽器端的amd 服務器端的commonjs  es6 不要說,還有ts

而且package.json,tsconfig.json往往都要自己修改配置,要知道改這個(習慣cli接口,習慣命令行參數的,會好受些)。

現在就體會到py的好了:果然魚最難感知的就是水的存在。

1 py有大而全的標准庫,30多個主題,我寫到今天也不敢保證都用過。保證了開箱即用,不需要這樣自己東1個庫,西1個庫。即使py的標准庫往往不是實際中最優的庫,但是對上手來說,夠用了。單元測試不用必須手動安裝pytest,用自帶的unittest就基本夠用了。

總的感覺是pip庫質量比npm高很多。node也就是flask一樣的微框架而已。

2 py代碼本身風格就很整齊。自從09年2/3代切換之后,就更沒什么坑。

記錄一些從py開發者角度看遇到的很別扭的坑。

 

1 @types

為了ts使用而 npm i @types/XXX,但這個並不能代替XXX本身的安裝。

可以理解成@types只是為js庫提供了index.d.ts 這樣的帶有類型注解的導出聲明而已。如果js庫類似於是.c的話,@types就類似於給加了一個.h文件。

不能代替.c本身。

所以用d3 npm i d3 @types/d3  都要裝,其他庫同理.

 

2 單元測試

要用到mocha和chai。

注意, 因為是用ts,所以在package.json里這樣寫:

"scripts": {
"build-ts": "tsc",
"start": "ts-node src/server.ts",
"start:dev": "nodemon",
"serve": "node dist/server.js",
"test": "mocha --require ts-node/register test/**/*.ts"
},

test得寫成這樣,注意還用到了ts-node。

測試用例在根目錄的test路徑下 .ts結尾 測試用例的例子:

import { expect } from 'chai';
import 'mocha';

import {helloworld} from '../src/a.ts'
describe('Hello function', () => {
  it('should return hello world', () => {
  const result = helloword();
   expect(result).to.equal('Hello World!');
});
})

然后是在vscode里file 首選項,鍵盤快捷方式里,搜索run test  找到運行全部測試用例。設置一個快捷鍵。我給了ctrl+alt+t

 這樣就可以單元測試了。

3node中module的導入

分為2種情況

3.1 第三方庫

安裝在node_modules里的那些。

因為我是用ts寫,所以 npm i XXX @types/XXX 是可以的,

不過在node里用,還是有node版就直接裝node版的 d3-node最省事

而且,在tsconfig,json里因為"module":是 "commonjs",

{
"compilerOptions": {
  "module": "commonjs",
}

所以,在ts文件里,也可以直接按node的commonjs的寫法:

var d3 = require('d3');
這樣用。
不必須import from,  node畢竟不是ng。

3.2自己寫的代碼庫

 又分好幾種情況

服務器端用:

1ts寫,供ts調用

其實反而和es6差不多,直接結尾export {}即可,最簡單。

還可能將來復用到ng等等別的地方。

2 js寫,commonjs方式,供ts調用

直接node的commonjs方式 文件結尾 module.exports = {XXX,}
如果只准備在node端用的代碼,這樣也夠了,但不如1

3 es6寫的js,供ts調用

 這樣的目的,是試圖這個js庫准備兼容瀏覽器和服務端,兩邊都使用。

如果js里是es6的寫法 export {}   直接執行測試,會報錯,SyntaxError: Unexpected token export

怎么都搞不定,還是看ts官網 Migrating from JavaScript

在tsconfig.json里加入

"compilerOptions": {
"module": "commonjs",
"resolveJsonModule": true,
"esModuleInterop": true,
"target": "es6",
"noImplicitAny": false,
"allowJs": true,
...
}

直接搞定。

原因:

如果沒有這個選項,那么tsc遇到js時不處理,然后node用commonjs模塊機制處理,那么目前就還不認識export關鍵字。所以報錯了;

如果打開這個選項,tsc會去處理js文件,ts是認識exports關鍵字的,在別處 import from 就沒事了。

——坑點:TM這個選項,還有很多別的選項,可能沒列在默認的tsconfig.json里啊啊啊(tsconfig.json也許來自其他地方copy過來的,2333)。那么tsc是個超多選項的cli,那么多默認參數,新手不可能每個都知道。如果tsconfig.json寫漏了就麻煩了。

 

4 noImplicitAny ,  true or false?

tsconfig.json里的noImplicitAny可以控制:
如果true,函數的形參必須帶類型,如果叫不出class名的js對象,那就得any,比如(d:any)=>{}
如果false,函數的樣子更像js  (d)=>{}
 
到底用不用強制寫class?
 
如果false,而且確實什么類型注解都不寫,那么用ts的意思其實不大了,直接寫原生的es6就可以了,推薦阮一峰老師的《ES6標准入門 第3版》
但是true的話,又到處都是any尤其是(d:any)=>{} ,確實很丑,很沒有必要,ts的類型聲明只是注解,畢竟還是要轉成js執行的。ts也畢竟不是java,我也不是java程序員。
而且,現在寫了這么久的代碼,自己的感覺不是“一切都是類”,“一切都是函數”,“一切都是文件”,而是“該是class的才是class,該是function的,就是function”。
 
一個工程就好像一支軍隊,成軍之法:
既可以是正規軍的“有狀態的部隊”寫法:namespace下轄class,class下轄method
也可以是扁平化,“無狀態的分隊”寫法: module轄var,function
 
我的ts,不能給搞成完全沒有類型的史前js;也不能矯枉過正,強制搞成了java,搞得一切必須弄成class,層層的封裝。
 
所以,最佳選擇是獲得更多的選擇權:
保留不加類型注解的權利,也要獲得加類型注解的權利。
 因此
1 這個選項設置為false。自定義的ts類加注解(寫node畢竟不是用ng寫web component,沒有那么多class),string number這樣的基本類型加注解。
2 其他的地方不加類型注解,特別是d3 數據綁定時等等常用的(d)=>{}寫法,繼續保留不加注解的寫法。
 這樣用起來,更像py,哈哈哈


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM