摘要:但是,從長(zhǎng)遠(yuǎn)來(lái)看,尤其是多人協(xié)作的項(xiàng)目,還是很有必要的。第二參數(shù)為了某些場(chǎng)景下要大寫(xiě)強(qiáng)調(diào),只需要傳入即可自動(dòng)將結(jié)果轉(zhuǎn)成大寫(xiě)。這個(gè)有可能是業(yè)務(wù)上線了之后才發(fā)生,直接導(dǎo)致業(yè)務(wù)不可用。而這也被證明是個(gè)好的編碼方式。
只是抱著嘗試的心態(tài)對(duì)項(xiàng)目進(jìn)行了遷移,體驗(yàn)了一番typeScript的強(qiáng)大,當(dāng)然,習(xí)慣了JavaScript的靈活,弱類型,剛用上typeScript時(shí)會(huì)很不適應(yīng),猶如懶散慣了的人被突然箍上各種枷鎖,約束。但是,從長(zhǎng)遠(yuǎn)來(lái)看,尤其是多人協(xié)作的項(xiàng)目,還是很有必要的。
typescript的優(yōu)點(diǎn)靜態(tài)代碼檢查
可以規(guī)避一些容易被忽視,隱晦的邏輯或語(yǔ)法錯(cuò)誤,幫助我們寫(xiě)更加健壯,安全的代碼,如下所示
function getDefaultValue (key, emphasis) { let ret; if (key === "name") { ret = "GuangWong"; } else if(key=== "gender") { ret = "Man"; } else if (key === "age") { ret = 23; } else { throw new Error("Unkown key "); } if (emphasis) { ret = ret.toUpperCase(); } return ret; } getDefaultValue("name"); // GuangWong getDefaultValue("gender", true) // MAN getDefaultValue("age", true)
這是一個(gè)簡(jiǎn)單的函數(shù),第一個(gè)參數(shù) key 用來(lái)獲得一個(gè)默認(rèn)值。第二參數(shù) emphasis 為了某些場(chǎng)景下要大寫(xiě)強(qiáng)調(diào),只需要傳入 true 即可自動(dòng)將結(jié)果轉(zhuǎn)成大寫(xiě)。
但是如果不小心將 age 的值寫(xiě)成了數(shù)字字面量,如果我調(diào)用 getDefaultValue("age", true) 就會(huì)在運(yùn)行時(shí)報(bào)錯(cuò)。這個(gè)有可能是業(yè)務(wù)上線了之后才發(fā)生,直接導(dǎo)致業(yè)務(wù)不可用。
提高效率,錯(cuò)誤在編寫(xiě)代碼時(shí)報(bào)錯(cuò),而非編譯階段
如有一種場(chǎng)景,在代碼重構(gòu)遷移模塊目錄時(shí),一些模塊依賴引用路徑變更,或者是引用的模塊還沒(méi)安裝,不存在時(shí),配合vscode, 及時(shí)指出錯(cuò)誤,不用等跑一遍編譯
這種情況也適用于引用非定義變量等錯(cuò)誤
- 增強(qiáng)代碼的可讀性,可以做到代碼即文檔。
雖然代碼有注釋,但是并不是每個(gè)人都有良好的習(xí)慣
react 組件設(shè)計(jì) export interface CouponProps { coupons: CouponItemModel[]; } export interface couponState { page: number, size: number } class CouponContainer extends React.Component{ render() { return ( { this.props.coupons.map((item: CouponItemModel) => item.title) }) } } 使用 JS 寫(xiě)的 Component,Props 和 State表現(xiàn)的并不明顯。使用 Typescript 編寫(xiě) React 組件,需要為組件定義好 Props 和 State。而這也被證明是個(gè)好的編碼方式。其可以幫助你構(gòu)建更健壯的組件,別人經(jīng)手自己的代碼時(shí)可以很清楚知道一個(gè)組件需要傳入哪些參數(shù)
- 增強(qiáng)設(shè)計(jì)
相關(guān)實(shí)踐實(shí)踐是消弭困惑最好的方式,抱著好奇,排斥的心態(tài)還是對(duì)對(duì)項(xiàng)目進(jìn)行了遷徙
項(xiàng)目目錄介紹
--
如上圖所示,項(xiàng)目中所有源碼都放在src目錄中,src/client為客戶端的源碼,src/server為服務(wù)器端的代碼,dist目錄是編譯后的目錄
2. typescript In node2.1.準(zhǔn)備階段
使用npm安裝:npm install -g typescript,當(dāng)前項(xiàng)目使用了是v2.8.3
2.2 tsconfig.json
在項(xiàng)目的根目錄下新建立tsconfig.json文件,并編輯相關(guān)配置項(xiàng)
{ "compilerOptions": { "module": "commonjs", "target": "es5", "noImplicitAny": true, "sourceMap": true, "lib": ["es6", "dom"], "outDir": "dist", "baseUrl": ".", "jsx": "react", "paths": { "*": [ "node_modules/*", "src/types/*" ] } }, "include": [ "src/**/*" ] }
相關(guān)配置解析可參考tsconfig.json
2.3 結(jié)合gulp
var gulp = require("gulp"); var pump = require("pump"); var webpack = require("webpack"); var gutil = require("gulp-util"); var webpackDevConfig = require(__dirname + "/webpack.config.dev.js"); var ts = require("gulp-typescript"); var livereload = require("gulp-livereload"); var tsProject = ts.createProject("tsconfig.json"); gulp.task("compile:tsc:server", function () { return gulp.src("src/server/**/*.ts") .pipe(tsProject()) .pipe(gulp.dest("dist/server")); }); gulp.task("compile:tsc:client", function(callback){ webpack(webpackDevConfig, function(err, stats){ if(err) throw new gutil.PluginError("webpack:build-js", err); gutil.log("[webpack:build-js]", stats.toString({ colors: true })); callback(); }); }); //將任務(wù)同步執(zhí)行 var gulpSequence = require("gulp-sequence"); gulp.task("copy:html", function() { return pump([ gulp.src("./src/views/**/*"), gulp.dest("./dist/server/views") ]) }); gulp.task("compile", gulpSequence( "compile:tsc:server", "compile:tsc:client", "copy:html" )) gulp.task("watch", ["compile"], function() { livereload.listen(); gulp.watch(["./src/server/**/*.ts"], ["compile:tsc:server"]); gulp.watch(["./src/client/**/*.ts"], ["compile:tsc:client"]); gulp.watch(["./src/views/**/*.html"], ["copy:html"]); })
2.4 測(cè)試
在src/server/app.ts下編寫(xiě)代碼
///import * as express from "express"; import * as compression from "compression"; // compresses requests import * as cookieParser from "cookie-parser"; import * as bodyParser from "body-parser"; import * as path from "path"; import * as favicon from "serve-favicon"; import * as fs from "fs"; global.APP_PATH = __dirname; const programConfig = require(path.join(global.APP_PATH + "../../../config/index")); global.config = programConfig.get("config"); const mainRouters = require("./routers/main"); const underscore = require("underscore"); global._ = underscore._; const app = express(); // parse application/x-www-form-urlencoded app.use(bodyParser.urlencoded({ extended: false })); // parse application/json app.use(bodyParser.json()); // protocal app.use(function(req: express.Request, res: express.Response, next: express.NextFunction) { app.locals.protocol = req.protocol; app.locals.host = req.headers.host; next(); }); // view engine setup app.set("views", path.join(__dirname, "./views")); app.set("view engine", "jade"); app.engine("html", require("ejs-mate")); app.use(compression()); app.use(cookieParser()); // resources const cacheOptions = { maxAge : "1d", }; app.use("/test", express.static(path.join(__dirname, "../public"), cacheOptions)); app.use("/", mainRouters); const port = process.env.PORT || programConfig.get("config").port; const server = app.listen(port, function() { console.log("App is runing"); console.log("server is listening on " + port); }); module.exports = app;
2.5 遇到的問(wèn)題
動(dòng)態(tài)地為global添加屬性
由于js靈活的風(fēng)格,我們經(jīng)常動(dòng)態(tài)地為某一對(duì)象添加屬性,但是typeScript是編譯型語(yǔ)言,基本原則是先定義再使用,所以當(dāng)我們像下面這么引用
global.testName = "哈哈";
便會(huì)出現(xiàn)這樣的錯(cuò)誤
類型“Global”上不存在屬性“testName”
解決方法
(1)將global強(qiáng)制轉(zhuǎn)化為any類型 (global).testName = "哈哈" (2)擴(kuò)展原有的對(duì)象 global.prototy.testName = "哈哈哈" (3)使用.d.ts文件
declare namespace NodeJS { export interface Global { testName: string; } }
網(wǎng)上很多方法是直接添加一個(gè).d.ts文件即可,但是親測(cè)無(wú)效,需要在引用文件引入該文件,如本項(xiàng)目在app.ts文件中引入了
///集成單元測(cè)試
項(xiàng)目用的測(cè)試框架是 jest + enzyme
安裝 jest
npm i -D jest @types/jest
npm i -D ts-jest
安裝 enzyme
npm i -D enzyme @types/enzyme
配置 jest.config.js 文件
module.exports = { collectCoverage: true, moduleFileExtensions: [ "ts", "js", "tsx" ], transform: { "^.+.tsx?$": "ts-jest", }, testMatch: [ "**/test/**/*.test.(ts|js|tsx)" ], testEnvironment: "node" };
4.編寫(xiě)測(cè)試用例 coupon.test.tsx
import * as React from "react"; import { shallow, configure } from "enzyme"; import * as Adapter from "enzyme-adapter-react-16"; configure({ adapter: new Adapter()}) test("Jest-React-TypeScript 嘗試運(yùn)行", () => { const renderer = shallow(hello world) expect(renderer.text()).toEqual("hello world") })
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/95387.html
摘要:遷移概念是基于之上重寫(xiě)的全新框架。從遷移雖然應(yīng)用需要對(duì)其語(yǔ)法結(jié)構(gòu)進(jìn)行更新,但是開(kāi)發(fā)人員仍然可以通過(guò)和這兩篇文章來(lái)積極的確保升級(jí)工作符合最佳的應(yīng)用實(shí)踐。這可以很容易的讓一個(gè)的控制器遷移為一個(gè)的類。 遷移概念 Ionic 2 是基于 Angular 2 之上重寫(xiě)的全新框架。所有你已知的關(guān)于的 Angular 的部分仍然存在,但是也有一些作為開(kāi)發(fā)人員仍要了解的新的語(yǔ)法和結(jié)構(gòu)性變化。關(guān)于 An...
摘要:斯坦福宣布使用作為計(jì)算機(jī)課程的首選語(yǔ)言近日,某位有年教學(xué)經(jīng)驗(yàn)的斯坦福教授決定放棄,而使用作為計(jì)算機(jī)入門(mén)課程的教學(xué)語(yǔ)言。斯坦福官方站點(diǎn)將它們新的課程描述為是最流行的構(gòu)建交互式的開(kāi)發(fā)語(yǔ)言,本課程會(huì)用講解中的實(shí)例。 前端每周清單第 11 期:Angular 4.1支持TypeScript 2.3,Vue 2.3優(yōu)化服務(wù)端渲染,優(yōu)秀React界面框架合集 為InfoQ中文站特供稿件,首發(fā)地址為...
摘要:眾所周知,在大公司中進(jìn)行大的改革很難。目前公司有超過(guò)名開(kāi)發(fā)人員,其中有個(gè)以上是前端。從年起,已經(jīng)在一些小規(guī)模團(tuán)隊(duì)中探索使用。在年的前端調(diào)查中,靜態(tài)類型系統(tǒng)呼聲最高。在我們的主倉(cāng)庫(kù)中,絕大多數(shù)的公共依賴都已經(jīng)由做到了類型聲明。 特別說(shuō)明 這是一個(gè)由simviso團(tuán)隊(duì)進(jìn)行的關(guān)于Airbnb大規(guī)模應(yīng)用TypeScript分享的翻譯文檔,分享者是Airbnb的高級(jí)前端開(kāi)發(fā)Brie Bunge ...
摘要:我應(yīng)該使用編譯器標(biāo)志嗎編譯器選項(xiàng)所做的,基本上是將從可選類型語(yǔ)言轉(zhuǎn)換為強(qiáng)制類型檢驗(yàn)語(yǔ)言。由于在實(shí)際情況中顯式地聲明被認(rèn)為是不好的實(shí)踐,所以在開(kāi)發(fā)過(guò)程的早期,您就需要分配正確的類型。因此,我的建議是將設(shè)置為。 我應(yīng)該使用noImplicitAny TypeScript編譯器標(biāo)志嗎? noImplicitAny編譯器選項(xiàng)所做的,基本上是將TypeScript從可選類型語(yǔ)言轉(zhuǎn)換為強(qiáng)制類型檢驗(yàn)...
摘要:面對(duì)越來(lái)越火的,我們公司今年也逐漸開(kāi)始擁抱。綜上所述,我個(gè)人覺(jué)得是要?jiǎng)h除相關(guān)的東西,降低項(xiàng)目復(fù)雜度。但是有一個(gè)例外情況。這個(gè)配置項(xiàng)有三個(gè)值可選擇,分別是和。模式會(huì)生成,在使用前不需要再進(jìn)行轉(zhuǎn)換操作了,輸出文件的擴(kuò)展名為。 拋轉(zhuǎn)引用 現(xiàn)在越來(lái)越多的項(xiàng)目放棄了javascript,而選擇擁抱了typescript,就比如我們熟知的ant-design就是其中之一。面對(duì)越來(lái)越火的typesc...
閱讀 3735·2021-11-24 09:39
閱讀 1894·2021-11-16 11:45
閱讀 623·2021-11-16 11:45
閱讀 1044·2021-10-11 10:58
閱讀 2489·2021-09-09 11:51
閱讀 1948·2019-08-30 15:54
閱讀 699·2019-08-29 13:13
閱讀 3477·2019-08-26 12:18