国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

javascript 遷移 typescript 實踐

niceforbear / 2910人閱讀

摘要:但是,從長遠來看,尤其是多人協作的項目,還是很有必要的。第二參數為了某些場景下要大寫強調,只需要傳入即可自動將結果轉成大寫。這個有可能是業務上線了之后才發生,直接導致業務不可用。而這也被證明是個好的編碼方式。

只是抱著嘗試的心態對項目進行了遷移,體驗了一番typeScript的強大,當然,習慣了JavaScript的靈活,弱類型,剛用上typeScript時會很不適應,猶如懶散慣了的人被突然箍上各種枷鎖,約束。但是,從長遠來看,尤其是多人協作的項目,還是很有必要的。

typescript的優點

靜態代碼檢查

可以規避一些容易被忽視,隱晦的邏輯或語法錯誤,幫助我們寫更加健壯,安全的代碼,如下所示

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)

這是一個簡單的函數,第一個參數 key 用來獲得一個默認值。第二參數 emphasis 為了某些場景下要大寫強調,只需要傳入 true 即可自動將結果轉成大寫。

但是如果不小心將 age 的值寫成了數字字面量,如果我調用 getDefaultValue("age", true) 就會在運行時報錯。這個有可能是業務上線了之后才發生,直接導致業務不可用。

提高效率,錯誤在編寫代碼時報錯,而非編譯階段

如有一種場景,在代碼重構遷移模塊目錄時,一些模塊依賴引用路徑變更,或者是引用的模塊還沒安裝,不存在時,配合vscode, 及時指出錯誤,不用等跑一遍編譯

這種情況也適用于引用非定義變量等錯誤

- 增強代碼的可讀性,可以做到代碼即文檔。

雖然代碼有注釋,但是并不是每個人都有良好的習慣

react 組件設計

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 寫的 Component,Props 和 State表現的并不明顯。使用 Typescript 編寫 React 組件,需要為組件定義好 Props 和 State。而這也被證明是個好的編碼方式。其可以幫助你構建更健壯的組件,別人經手自己的代碼時可以很清楚知道一個組件需要傳入哪些參數

- 增強設計

相關實踐

實踐是消弭困惑最好的方式,抱著好奇,排斥的心態還是對對項目進行了遷徙

項目目錄介紹

--

如上圖所示,項目中所有源碼都放在src目錄中,src/client為客戶端的源碼,src/server為服務器端的代碼,dist目錄是編譯后的目錄

2. typescript In node

2.1.準備階段
使用npm安裝:npm install -g typescript,當前項目使用了是v2.8.3

2.2 tsconfig.json
在項目的根目錄下新建立tsconfig.json文件,并編輯相關配置項

{
  "compilerOptions": {
      "module": "commonjs",
      "target": "es5",
      "noImplicitAny": true,
      "sourceMap": true,
      "lib": ["es6", "dom"],
      "outDir": "dist",
      "baseUrl": ".",
      "jsx": "react",
      "paths": {
          "*": [
              "node_modules/*",
              "src/types/*"
          ]
      }
  },
  "include": [
      "src/**/*"
  ]
}

相關配置解析可參考tsconfig.json

2.3 結合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();
    });
});
  
//將任務同步執行
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 測試
src/server/app.ts下編寫代碼

/// 

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 遇到的問題

動態地為global添加屬性

由于js靈活的風格,我們經常動態地為某一對象添加屬性,但是typeScript是編譯型語言,基本原則是先定義再使用,所以當我們像下面這么引用

global.testName = "哈哈";

便會出現這樣的錯誤

類型“Global”上不存在屬性“testName”

解決方法

(1)將global強制轉化為any類型

 (global).testName = "哈哈"
    
(2)擴展原有的對象

  global.prototy.testName = "哈哈哈"

(3)使用.d.ts文件
declare namespace NodeJS {
 
  export interface Global {
    testName: string;
  }
}

網上很多方法是直接添加一個.d.ts文件即可,但是親測無效,需要在引用文件引入該文件,如本項目在app.ts文件中引入了

/// 
集成單元測試

項目用的測試框架是 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.編寫測試用例 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 嘗試運行", () => {
  const renderer = shallow(
hello world
) expect(renderer.text()).toEqual("hello world") })

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95387.html

相關文章

  • 從 Ionic1 遷移至 Ionic2 基本說明

    摘要:遷移概念是基于之上重寫的全新框架。從遷移雖然應用需要對其語法結構進行更新,但是開發人員仍然可以通過和這兩篇文章來積極的確保升級工作符合最佳的應用實踐。這可以很容易的讓一個的控制器遷移為一個的類。 遷移概念 Ionic 2 是基于 Angular 2 之上重寫的全新框架。所有你已知的關于的 Angular 的部分仍然存在,但是也有一些作為開發人員仍要了解的新的語法和結構性變化。關于 An...

    shevy 評論0 收藏0
  • 前端每周清單第 11 期:Angular 4.1支持TypeScript 2.3,Vue 2.3優化

    摘要:斯坦福宣布使用作為計算機課程的首選語言近日,某位有年教學經驗的斯坦福教授決定放棄,而使用作為計算機入門課程的教學語言。斯坦福官方站點將它們新的課程描述為是最流行的構建交互式的開發語言,本課程會用講解中的實例。 前端每周清單第 11 期:Angular 4.1支持TypeScript 2.3,Vue 2.3優化服務端渲染,優秀React界面框架合集 為InfoQ中文站特供稿件,首發地址為...

    warkiz 評論0 收藏0
  • 大規模應用TypeScript「2019 JSConf -Brie Bunge」

    摘要:眾所周知,在大公司中進行大的改革很難。目前公司有超過名開發人員,其中有個以上是前端。從年起,已經在一些小規模團隊中探索使用。在年的前端調查中,靜態類型系統呼聲最高。在我們的主倉庫中,絕大多數的公共依賴都已經由做到了類型聲明。 特別說明 這是一個由simviso團隊進行的關于Airbnb大規模應用TypeScript分享的翻譯文檔,分享者是Airbnb的高級前端開發Brie Bunge ...

    qpal 評論0 收藏0
  • TypeScript最佳實踐:是否使用noImplicitAny

    摘要:我應該使用編譯器標志嗎編譯器選項所做的,基本上是將從可選類型語言轉換為強制類型檢驗語言。由于在實際情況中顯式地聲明被認為是不好的實踐,所以在開發過程的早期,您就需要分配正確的類型。因此,我的建議是將設置為。 我應該使用noImplicitAny TypeScript編譯器標志嗎? noImplicitAny編譯器選項所做的,基本上是將TypeScript從可選類型語言轉換為強制類型檢驗...

    shiguibiao 評論0 收藏0
  • React項目從JavascriptTypescript遷移經驗總結

    摘要:面對越來越火的,我們公司今年也逐漸開始擁抱。綜上所述,我個人覺得是要刪除相關的東西,降低項目復雜度。但是有一個例外情況。這個配置項有三個值可選擇,分別是和。模式會生成,在使用前不需要再進行轉換操作了,輸出文件的擴展名為。 拋轉引用 現在越來越多的項目放棄了javascript,而選擇擁抱了typescript,就比如我們熟知的ant-design就是其中之一。面對越來越火的typesc...

    zhisheng 評論0 收藏0

發表評論

0條評論

niceforbear

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<