成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

javascript 遷移 typescript 實(shí)踐

niceforbear / 2918人閱讀

摘要:但是,從長(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 node

2.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

相關(guān)文章

  • 從 Ionic1 遷移至 Ionic2 基本說(shuō)明

    摘要:遷移概念是基于之上重寫(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...

    shevy 評(píng)論0 收藏0
  • 前端每周清單第 11 期:Angular 4.1支持TypeScript 2.3,Vue 2.3優(yōu)化

    摘要:斯坦福宣布使用作為計(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ā)地址為...

    warkiz 評(píng)論0 收藏0
  • 大規(guī)模應(yīng)用TypeScript「2019 JSConf -Brie Bunge」

    摘要:眾所周知,在大公司中進(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 ...

    qpal 評(píng)論0 收藏0
  • TypeScript最佳實(shí)踐:是否使用noImplicitAny

    摘要:我應(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)...

    shiguibiao 評(píng)論0 收藏0
  • React項(xiàng)目從JavascriptTypescript遷移經(jīng)驗(yàn)總結(jié)

    摘要:面對(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...

    zhisheng 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<