摘要:接下來來看一段代碼示例語法與語言比較當(dāng)類型不對的時候,會提示錯誤編譯后語法聯(lián)想大致可以把它看成是加了類型系統(tǒng)的。
一篇文章學(xué)會 TypeScript (內(nèi)部分享標(biāo)題:TypeScript 基礎(chǔ))
這篇文章是我在公司前端小組內(nèi)部的演講分享稿,目的是教會大家使用 TypeScript,1、什么是 TypeScript?
這篇文章雖然標(biāo)著基礎(chǔ),但我指的基礎(chǔ)是學(xué)完后就能夠勝任 TypeScript 的開發(fā)工作。
從我分享完的效果來看,大家都學(xué)會了,效果還是好的。我把這篇分享稿發(fā)布出來,
希望能對大家的 TypeScript 學(xué)習(xí)有所幫助。
TypeScript 是由微軟發(fā)布的一款開源的編程語言。它是 JavaScript 的超集(兼容 JavaScript 代碼),其代碼必須經(jīng)過編譯后,方可在 JavaScript 環(huán)境中運(yùn)行,核心功能是類型系統(tǒng)和可以提前使用 ES 的新特性。
接下來來看一段代碼示例:
// TypeScript 語法 function add(x: number, y: number): number { const res: number = x + y; return res; } // 與 C 語言比較 int add(int x, int y) { int res = x + y; return res; }
當(dāng)類型不對的時候,IDE 會提示錯誤:
編譯后:
// JavaScript 語法 function add(x, y) { const res = x + y; return res; }
聯(lián)想:大致可以把它看成是加了類型系統(tǒng)的 Babel。
問題:為什么要學(xué)習(xí) TypeScript?類型系統(tǒng)可以在代碼編譯階段就可以發(fā)現(xiàn)潛在的變量類型問題,甚至在開發(fā)階段,IDE 就可以幫助我們找到這些潛在的問題,避免了項(xiàng)目在上線后才發(fā)現(xiàn)變量類型不對的錯誤。
TypeScript 是前端開發(fā)的趨勢,有些特性還可能會成為 ES 的新標(biāo)準(zhǔn),Vue 3.0 也會采用 TypeScript 作為開發(fā)語言,當(dāng)你想看源碼的時候不至于看不懂,跟著趨勢走肯定是沒錯的。
減少類型校驗(yàn)等無用的代碼書寫。
可以提前享受 ES 新特性帶來的便利。
向 qian 看,qian 途。
2、快速上手,三步走 第一步:全局安裝 TypeScript$ yarn global add typescript // 測試是否安裝成功 $ tsc -v Version 3.4.5第二步:創(chuàng)建 .ts 文件
// add.ts function add(x: number, y: number): number { const res: number = x + y; return res; } export default add;第三步:編譯
$ tsc add.ts
// add.js function add(x, y) { const res = x + y; return res; } export default add;文件監(jiān)聽,實(shí)時編譯
適用于邊開發(fā)邊看結(jié)果的情況:
$ tsc -w add.ts Starting compilation in watch mode... Watching for file changes.3、TypeScript 的基本類型
// 布爾值 let isDone: boolean = false; // 數(shù)值 let age: number = 12; // 字符串 let name: string = "Jay"; // 數(shù)組 let list: number[] = [1, 2, 3]; let list: Array4、類和接口= [1, 2, 3]; // 對象 let mokey: object = {name: "wu kong"}; // 空值,表示沒有返回值 function print(): void {} // 任意值 let goods: any = {}; let goods: any = 2019; // 未指定類型,視為任意值 let goods; // 類型推斷 let name = "Jay"; name = 123; // 報錯 // 聯(lián)合類型 let name: string | number; name = "Jay"; name = 123;
類是對屬性和方法的封裝
類的示例:
// 跟 JavaScript 的類相似,多了訪問控制等關(guān)鍵詞 class Monkey { public height: number; private age: number = 12; public static mkName: string = "kinkong"; private static action: string = "jump"; constructor(height: number) { this.height = height; } public getAge(): number { return this.age; } } const monkey = new Monkey(120); monkey.getAge(); const height = monkey.height; const age = monkey.age; // 報錯 const mkName = Monkey.mkName; const action = Monkey.action; // 報錯
class Animal { move(distanceInMeters: number = 0) { console.log(`Animal moved ${distanceInMeters}m.`); } } class Dog extends Animal { bark() { console.log("Woof! Woof!"); } } const dog = new Dog(); dog.bark(); dog.move(10);
protected 和 private 都不能從外部訪問
protected 可以被繼承,private 不可以
class Person { protected name: string; private age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } } class Employee extends Person { private readonly initial: string = "abc"; private readonly department: string; constructor(name: string, department: string) { super(name, 1); this.department = department; } public getElevatorPitch() { return `Hello, my name is ${this.name} and I work in ${this.department}.`; } public getAge() { return this.age; } } let howard = new Employee("Howard", "Sales"); console.log(howard.getElevatorPitch()); console.log(howard.name); // error
let passcode = "secret passcode"; class Employee { private _fullName: string; get fullName(): string { return this._fullName; } set fullName(newName: string) { if (passcode && passcode == "secret passcode") { this._fullName = newName; } else { console.log("Error: Unauthorized update of employee!"); } } } let employee = new Employee(); employee.fullName = "Bob Smith"; if (employee.fullName) { console.log(employee.fullName); }
class Point { x: number; y: number; } interface Point3d extends Point { z: number; } let point3d: Point3d = {x: 1, y: 2, z: 3};
接口是用來定義規(guī)范的,常常用作類型說明。
接口的示例:
// 定義規(guī)范,限定類型 interface Point { x: number; y: number; // 可選屬性 z?: number; } let pt: Ponit = {x: 1, y: 1, z: 1}; function setPoint(point: Point): void {} setPoint({x: 1, y: 1}); // 實(shí)現(xiàn)接口 class point implements Point { x: number; y: number; constructor(x: number, y: number) { this.x = x; this.y = y; } public getPoint(): object { return { x: this.x, y: this.y, } } } const p = new point(3, 4); p.getPoint();
interface Shape { color: string; } interface Square extends Shape { sideLength: number; }
interface ClockConstructor { new (hour: number, minute: number); } class Clock implements ClockConstructor { currentTime: Date; constructor(h: number, m: number) { } }5、type、 namespace 和泛型 type 定義新類型
當(dāng) TypeScript 提供的類型不夠用時,可以用來自定義類型,供自己使用。
// type 定義新類型,相當(dāng)于類型別名 type myType = string | number | boolean // 使用: const foo: myType = "foo" // type 定義函數(shù)類型 type hello = (msg: string) => void // type 對象類型 type WebSite = { url: string; title: number; }namespace 命名空間
命名空間主要有兩個方面的用途:
組織代碼。組織一些具有內(nèi)在聯(lián)系的特性和對象,能夠使代碼更加清晰。
避免名稱沖突。
namespace Validator { export interface StringValidator { isAcceptable(s: string): boolean; } const lettersRegexp = /^[A-Za-z]+$/; const numberRegexp = /^[0-9]+$/; // 當(dāng)聲明一個命名空間的時候,所有實(shí)體部分默認(rèn)是私有的,可以使用 export 關(guān)鍵字導(dǎo)出公共部分。 export class LettersOnlyValidator implements StringValidator { isAcceptable(s: string) { return lettersRegexp.test(s); } } export class ZipCodeValidator implements StringValidator { isAcceptable(s: string) { return s.length === 5 && numberRegexp.test(s); } } } new Validator.LettersOnlyValidator(); interface MyClassMethodOptions { name?: string; age?: number; } namespace MyClass { export interface MyClassMethodOptions { width?: number; height?: number; } }
///泛型const v = new Validator.LettersOnlyValidator();
泛型允許在強(qiáng)類型程序設(shè)計(jì)語言中編寫代碼時,使用一些以后才指定的類型,在實(shí)際調(diào)用時才去指定泛型的類型。
舉例:
// 模擬服務(wù),提供不同的數(shù)據(jù)。這里模擬了一個字符串和一個數(shù)值 const service = { getStringValue: function() { return "a string value"; }, getNumberValue: function() { return 20; } }; // 處理數(shù)據(jù)的中間件 function middleware(value: string): string { return value; } // 沒問題 middleware(service.getStringValue()); // 報錯:參數(shù)類型不對 middleware(service.getNumberValue()); // 設(shè)成 any 行不行? function middleware(value: any): any // 多寫幾個 middleware 行不行? function middleware1(value: string): string { ... } function middleware2(value: number): number { ... } // 改為泛型 function middleware(value: T): T { return value; } // 使用 middleware (service.getStringValue()); middleware (service.getNumberValue());
更多內(nèi)容查看文章:泛型
6、xxx.d.ts聲明文件如果把 add.js 發(fā)布成一個 npm 包,別人在使用的時候 IDE 的提示往往都不太友好:
那么如何能讓 IDE 給 add 方法加上類型提示和參數(shù)提示呢?
TypeScript 提供了 xxx.d.ts 文件來給 IDE 使用。
xxx.d.ts 叫做聲明文件,一般用于類型提示和模塊補(bǔ)充,可以自動生成,也可以手動編寫,一般情況下是不用我們手動編寫的。
// 加上 -d 參數(shù),就會生成 add.d.ts 文件 $ tsc -d add.ts
// add.d.ts declare function add(x: number, y: number): number; export default add;
declare 關(guān)鍵字
用于聲明你需要的變量、函數(shù)、類等,聲明以后 IDE 就可以根據(jù)它來進(jìn)行類型提示。
如果有 add.d.ts 文件,那么它就承擔(dān)了類型提示的任務(wù):
同時也相當(dāng)于 add 方法的接口文檔:
手動創(chuàng)建聲明文件有以下兩個場景會去手動創(chuàng)建這個文件:
給未使用 TypeScript 的 js 模塊編寫聲明文件,可以當(dāng)做交接文檔用;使用別人沒有寫聲明文件的 js 庫。
模塊補(bǔ)充。
// 定義模塊補(bǔ)充的語法 declare module "filePath" { }
module-augmentation
使用場景:vue-shim.d.ts 文件,為了讓 TypeScript 識別 .vue 文件。
// 文件內(nèi)容 declare module "*.vue" { import Vue from "vue"; export default Vue; }
增強(qiáng)類型以配合插件使用
7、配置文件 冗長的參數(shù)指定輸出目錄:
$ tsc -d --strict -m ESNext --outDir lib index.ts
tsc 的所有參數(shù)可以通過執(zhí)行:tsc -h來查看。
使用 tsconfig.json 配置文件避免書寫冗長的命令,豐富的配置項(xiàng)。
生成 tsconfig.json 文件:
$ tsc --init
常用配置項(xiàng)解讀:
{ "compilerOptions": { "target": "ES5", /* target用于指定編譯之后的版本目標(biāo) version: "ES3" (default), "ES5", "ES2015", "ES2016", "ES2017","ES2018" or "ESNEXT". */ "module": "ESNext", /* 用來指定要使用的模塊標(biāo)準(zhǔn): "none", "commonjs", "amd", "system", "umd", "es2015", or "ESNext". */ "declaration": true, /* 生成對應(yīng)的 ".d.ts" 聲明文件 */ "outDir": "./lib", /* 指定編譯輸出目錄 */ "esModuleInterop": true, /* 通過為導(dǎo)入內(nèi)容創(chuàng)建命名空間,實(shí)現(xiàn)CommonJS和ES模塊之間的互操作性 */ "experimentalDecorators": true, /* 啟用 ES7 裝飾器語法 */ } }
查看更多配置項(xiàng)
配置后,執(zhí)行以下命令,就會讀取配置文件:
$ tsc add.ts8、使用 TypeScript 開發(fā) web 應(yīng)用
上述的方法適用于開發(fā)命令行工具,比如 @xiyun/cli,開發(fā) web 應(yīng)用還是不太方便。
如果想要方便地開發(fā) web 應(yīng)用,比如:開啟前端服務(wù)、模塊熱加載等,就需要配合構(gòu)建工具使用。
配合 webpack 開發(fā) web 應(yīng)用點(diǎn)擊查看配合 webpack 開發(fā) web 應(yīng)用源碼
配合 parcel,零配置開發(fā) web 應(yīng)用parcel:極速零配置 Web 應(yīng)用打包工具。
聯(lián)想:可以看成是已經(jīng)配置好了的 webpack。
全局安裝 parcel 工具:
$ yarn global add parcel-bundler
運(yùn)行:
$ parcel index.html
它就會幫你生成 package.json,自動安裝 typeScript,啟動好開發(fā)服務(wù),并支持熱加載。
9、在 Vue 和 React 項(xiàng)目中使用 讓 Vue 支持 TypeScript最方便快捷:vue create my-app,選擇 TypeScript。
如果要改造現(xiàn)有項(xiàng)目:
增加 dev 依賴包:
"devDependencies": { "@vue/cli-plugin-typescript": "^3.8.0", "typescript": "^3.4.3", }
增加 tsconfig.json 配置
更改文件后綴:main.js --> main.ts
組件中指定 lang:
在 src 目錄下加上:vue-shim.d.ts 文件,為了讓 TypeScript 識別 .vue 文件。
// 文件內(nèi)容 declare module "*.vue" { import Vue from "vue"; export default Vue; }
Vue 支持 TypeScript 的配置參考
如果想要用這種語法來寫 Vue 組件:
import { Component, Prop, Vue } from "vue-property-decorator"; @Component export default class HelloWorld extends Vue { @Prop() private msg!: string; }
那么需要加上這兩個依賴:
"dependencies": { // 官網(wǎng)出的ts支持包 "vue-class-component": "^7.0.2", // 對ts支持包更好封裝的裝飾器 "vue-property-decorator": "^8.1.0" },
Vue 官方對 TypeScript 的說明
創(chuàng)建支持 TypeScript 的 React 項(xiàng)目創(chuàng)建應(yīng)用時加上--typescript參數(shù)即可:
$ create-react-app my-app --typescript參考資料
TypeScript 官方文檔
TypeScript Declare Keyword
Vue 對 模塊補(bǔ)充的說明
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/104318.html
摘要:周末是時隔兩月的家人團(tuán)聚,而每次內(nèi)容的準(zhǔn)備平均需要我集中精力工作小時,所以第期的內(nèi)容今早才準(zhǔn)備好,對不住大家了。下面是本周精選內(nèi)容,請享用。本文作者王仕軍,商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。 showImg(https://segmentfault.com/img/remote/1460000009742537?w=1240&h=509); 周末是時隔兩月的家人團(tuán)聚,而...
摘要:前言講起前端,我們就不能不講與,在這兩種技術(shù)廣泛應(yīng)用的今天,他們的擴(kuò)展也是層出不窮,的擴(kuò)展有等,的超集有等。如下注意你的樣式文件一定要在引入前先引入。截止目前,已經(jīng)發(fā)布了最新的版本。 前言:講起前端,我們就不能不講CSS與Javascript,在這兩種技術(shù)廣泛應(yīng)用的今天,他們的擴(kuò)展也是層出不窮,css的擴(kuò)展有Less、Sass、Stylus等,js的超集有Typescript等。今天我們就簡...
這只是個開頭 說在最前面,本文是一個系列文章的開頭, 這個系列里我會講如何用typescript開發(fā)一款支持pc和手機(jī)端的手勢庫any-touch, 以及通過jest讓你的代碼測試覆蓋率100%. showImg(https://segmentfault.com/img/bVbp3B0?w=936&h=246); 目錄 用TypeScript開發(fā)手勢庫 - (2)tsconfig.json & r...
摘要:前端進(jìn)階進(jìn)階構(gòu)建項(xiàng)目一配置最佳實(shí)踐狀態(tài)管理之痛點(diǎn)分析與改良開發(fā)中所謂狀態(tài)淺析從時間旅行的烏托邦,看狀態(tài)管理的設(shè)計(jì)誤區(qū)使用更好地處理數(shù)據(jù)愛彼迎房源詳情頁中的性能優(yōu)化從零開始,在中構(gòu)建時間旅行式調(diào)試用輕松管理復(fù)雜狀態(tài)如何把業(yè)務(wù)邏輯這個故事講好和 前端進(jìn)階 webpack webpack進(jìn)階構(gòu)建項(xiàng)目(一) Webpack 4 配置最佳實(shí)踐 react Redux狀態(tài)管理之痛點(diǎn)、分析與...
本文收集學(xué)習(xí)過程中使用到的資源。 持續(xù)更新中…… 項(xiàng)目地址 https://github.com/abc-club/f... 目錄 vue react react-native Weex typescript Taro nodejs 常用庫 css js es6 移動端 微信公眾號 小程序 webpack GraphQL 性能與監(jiān)控 高質(zhì)文章 趨勢 動效 數(shù)據(jù)結(jié)構(gòu)與算法 js core 代碼規(guī)范...
閱讀 965·2021-11-17 09:33
閱讀 424·2019-08-30 11:16
閱讀 2478·2019-08-29 16:05
閱讀 3361·2019-08-29 15:28
閱讀 1402·2019-08-29 11:29
閱讀 1958·2019-08-26 13:51
閱讀 3396·2019-08-26 11:55
閱讀 1214·2019-08-26 11:31