1、初識TypeScript

TypeScript 的介紹
TypeScript是一種由微軟開發(fā)的開源、跨平臺的編程語言。它是JavaScript的超集,最終會被編譯為JavaScript代碼。
2012年10月,微軟發(fā)布了首個公開版本的TypeScript,2013年6月19日,在經(jīng)歷了一個預(yù)覽版之后微軟正式發(fā)布了正式版TypeScript
TypeScript的作者是安德斯·海爾斯伯格,C#的首席架構(gòu)師。它是開源和跨平臺的編程語言。
TypeScript擴(kuò)展了JavaScript的語法,所以任何現(xiàn)有的JavaScript程序可以運(yùn)行在TypeScript環(huán)境中。
TypeScript是為大型應(yīng)用的開發(fā)而設(shè)計,并且可以編譯為JavaScript。
TypeScript 是 JavaScript 的一個超集,主要提供了類型系統(tǒng)和對 ES6+ 的支持,它由 Microsoft 開發(fā),代碼開源于 GitHub上
TypeScript 的特點(diǎn)
TypeScript 主要有 3 大特點(diǎn):
- 始于JavaScript,歸于JavaScript
TypeScript 可以編譯出純凈、 簡潔的 JavaScript 代碼,并且可以運(yùn)行在任何瀏覽器上、Node.js 環(huán)境中和任何支持 ECMAScript 3(或更高版本)的JavaScript 引擎中。
- 強(qiáng)大的類型系統(tǒng)
類型系統(tǒng)允許 JavaScript 開發(fā)者在開發(fā) JavaScript 應(yīng)用程序時使用高效的開發(fā)工具和常用操作比如靜態(tài)檢查和代碼重構(gòu)。
- 先進(jìn)的 JavaScript
TypeScript 提供最新的和不斷發(fā)展的 JavaScript 特性,包括那些來自 2015 年的 ECMAScript 和未來的提案中的特性,比如異步功能和 Decorators,以幫助建立健壯的組件。
總結(jié)
TypeScript 在社區(qū)的流行度越來越高,它非常適用于一些大型項(xiàng)目,也非常適用于一些基礎(chǔ)庫,極大地幫助我們提升了開發(fā)效率和體驗(yàn)。
2、 安裝 TypeScript
命令行運(yùn)行如下命令,全局安裝 TypeScript:
npm install -g typescript
安裝完成后,在控制臺運(yùn)行如下命令,檢查安裝是否成功(3.x):
tsc -V
3、第一個 TypeScript 程序
編寫 TS 程序
src/helloworld.ts
function greeter (person) {
return 'Hello, ' + person
}
let user = 'Yee'
console.log(greeter(user))
手動編譯代碼
我們使用了.ts擴(kuò)展名,但是這段代碼僅僅是 JavaScript 而已。
在命令行上,運(yùn)行 TypeScript 編譯器:
tsc helloworld.ts
輸出結(jié)果為一個 helloworld.js文件,它包含了和輸入文件中相同的 JavsScript 代碼。
在命令行上,通過 Node.js 運(yùn)行這段代碼:
node helloworld.js
控制臺輸出:
Hello, Yee
vscode自動編譯
1). 生成配置文件tsconfig.json
tsc --init
2). 修改tsconfig.json配置
"outDir": "./js",
"strict": false,
3). 啟動監(jiān)視任務(wù):
終端 -> 運(yùn)行任務(wù) -> 監(jiān)視tsconfig.json
類型注解
接下來讓我們看看 TypeScript 工具帶來的高級功能。 給 person函數(shù)的參數(shù)添加 :string 類型注解,如下:
function greeter (person: string) {
return 'Hello, ' + person
}
let user = 'Yee'
console.log(greeter(user))
TypeScript 里的類型注解是一種輕量級的為函數(shù)或變量添加約束的方式。 在這個例子里,我們希望 greeter 函數(shù)接收一個字符串參數(shù)。 然后嘗試把 greeter 的調(diào)用改成傳入一個數(shù)組:
function greeter (person: string) {
return 'Hello, ' + person
}
let user = [0, 1, 2]
console.log(greeter(user))
重新編譯,你會看到產(chǎn)生了一個錯誤:
error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'string'.
類似地,嘗試刪除 greeter調(diào)用的所有參數(shù)。 TypeScript 會告訴你使用了非期望個數(shù)的參數(shù)調(diào)用了這個函數(shù)。 在這兩種情況中,TypeScript提供了靜態(tài)的代碼分析,它可以分析代碼結(jié)構(gòu)和提供的類型注解。
要注意的是盡管有錯誤,greeter.js 文件還是被創(chuàng)建了。 就算你的代碼里有錯誤,你仍然可以使用 TypeScript。但在這種情況下,TypeScript 會警告你代碼可能不會按預(yù)期執(zhí)行。
接口
讓我們繼續(xù)擴(kuò)展這個示例應(yīng)用。這里我們使用接口來描述一個擁有 firstName 和 lastName 字段的對象。 在 TypeScript里,只在兩個類型內(nèi)部的結(jié)構(gòu)兼容,那么這兩個類型就是兼容的。 這就允許我們在實(shí)現(xiàn)接口時候只要保證包含了接口要求的結(jié)構(gòu)就可以,而不必明確地使用 implements 語句。
interface Person {
firstName: string
lastName: string
}
function greeter (person: Person) {
return 'Hello, ' + person.firstName + ' ' + person.lastName
}
let user = {
firstName: 'Yee',
lastName: 'Huang'
}
console.log(greeter(user))
類
最后,讓我們使用類來改寫這個例子。 TypeScript 支持 JavaScript 的新特性,比如支持基于類的面向?qū)ο缶幊獭?/p>
讓我們創(chuàng)建一個 User 類,它帶有一個構(gòu)造函數(shù)和一些公共字段。因?yàn)轭惖淖侄伟私涌谒枰淖侄危运麄兡芎芎玫募嫒荨?/p>
還要注意的是,我在類的聲明上會注明所有的成員變量,這樣比較一目了然。
class User {
fullName: string
firstName: string
lastName: string
constructor (firstName: string, lastName: string) {
this.firstName = firstName
this.lastName = lastName
this.fullName = firstName + ' ' + lastName
}
}
interface Person {
firstName: string
lastName: string
}
function greeter (person: Person) {
return 'Hello, ' + person.firstName + ' ' + person.lastName
}
let user = new User('Yee', 'Huang')
console.log(greeter(user))
重新運(yùn)行 tsc greeter.ts,你會看到 TypeScript 里的類只是一個語法糖,本質(zhì)上還是 JavaScript函數(shù)的實(shí)現(xiàn)。
4、使用webpack打包TS
下載依賴
npm install -D typescript
npm install -D webpack webpack-cli
npm install -D webpack-dev-server
npm install -D html-webpack-plugin clean-webpack-plugin
npm install -D ts-loader
npm install -D cross-env
入口JS: src/main.ts
document.write('Hello Webpack TS!')
index頁面: public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>webpack & TS</title>
</head>
<body>
</body>
</html>
build/webpack.config.js
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const path = require('path')
const isProd = process.env.NODE_ENV === 'production' // 是否生產(chǎn)環(huán)境
function resolve (dir) {
return path.resolve(__dirname, '..', dir)
}
module.exports = {
mode: isProd ? 'production' : 'development',
entry: {
app: './src/main.ts'
},
output: {
path: resolve('dist'),
filename: '[name].[contenthash:8].js'
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
include: [resolve('src')]
}
]
},
plugins: [
new CleanWebpackPlugin({
}),
new HtmlWebpackPlugin({
template: './public/index.html'
})
],
resolve: {
extensions: ['.ts', '.tsx', '.js']
},
devtool: isProd ? 'cheap-module-source-map' : 'cheap-module-eval-source-map',
devServer: {
host: 'localhost', // 主機(jī)名
stats: 'errors-only', // 打包日志輸出輸出錯誤信息
port: 8081,
open: true
},
}
配置打包命令
"dev": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.config.js",
"build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js"
運(yùn)行與打包
npm run dev
npm run build
5、其他
聲明文件
當(dāng)使用第三方庫時,我們需要引用它的聲明文件,才能獲得對應(yīng)的代碼補(bǔ)全、接口提示等功能
什么是聲明語句
假如我們想使用第三方庫 jQuery,一種常見的方式是在 html 中通過 <script> 標(biāo)簽引入 jQuery,然后就可以使用全局變量 $ 或 jQuery 了。
但是在 ts 中,編譯器并不知道 $ 或 jQuery 是什么東西
/*
當(dāng)使用第三方庫時,我們需要引用它的聲明文件,才能獲得對應(yīng)的代碼補(bǔ)全、接口提示等功能。
聲明語句: 如果需要ts對新的語法進(jìn)行檢查, 需要要加載了對應(yīng)的類型說明代碼
declare var jQuery: (selector: string) => any;
聲明文件: 把聲明語句放到一個單獨(dú)的文件(jQuery.d.ts)中, ts會自動解析到項(xiàng)目中所有聲明文件
下載聲明文件: npm install @types/jquery --save-dev
*/
jQuery('#foo');
// ERROR: Cannot find name 'jQuery'
這時,我們需要使用 declare var 來定義它的類型
declare var jQuery: (selector: string) => any;
jQuery('#foo');
declare var 并沒有真的定義一個變量,只是定義了全局變量 jQuery 的類型,僅僅會用于編譯時的檢查,在編譯結(jié)果中會被刪除。它編譯結(jié)果是:
jQuery('#foo');
一般聲明文件都會單獨(dú)寫成一個 xxx.d.ts 文件
創(chuàng)建 01_jQuery.d.ts, 將聲明語句定義其中, TS編譯器會掃描并加載項(xiàng)目中所有的TS聲明文件
declare var jQuery: (selector: string) => any;
很多的第三方庫都定義了對應(yīng)的聲明文件庫, 庫文件名一般為 @types/xxx, 可以在 https://www.npmjs.com/package/package 進(jìn)行搜索
有的第三庫在下載時就會自動下載對應(yīng)的聲明文件庫(比如:webpack),有的可能需要單獨(dú)下載(比如jQuery/react)
內(nèi)置對象
JavaScript 中有很多內(nèi)置對象,它們可以直接在 TypeScript 中當(dāng)做定義好了的類型。
內(nèi)置對象是指根據(jù)標(biāo)準(zhǔn)在全局作用域(Global)上存在的對象。這里的標(biāo)準(zhǔn)是指 ECMAScript 和其他環(huán)境(比如 DOM)的標(biāo)準(zhǔn)。
1.ECMAScript 的內(nèi)置對象
Boolean
Number
String
Date
RegExp
Error
/* 1. ECMAScript 的內(nèi)置對象 */
let b: Boolean = new Boolean(1)
let n: Number = new Number(true)
let s: String = new String('abc')
let d: Date = new Date()
let r: RegExp = /^1/
let e: Error = new Error('error message')
b = true
// let bb: boolean = new Boolean(2) // error
2.BOM 和 DOM 的內(nèi)置對象
Window
Document
HTMLElement
DocumentFragment
Event
NodeList
const div: HTMLElement = document.getElementById('test')
const divs: NodeList = document.querySelectorAll('div')
document.addEventListener('click', (event: MouseEvent) => {
console.dir(event.target)
})
const fragment: DocumentFragment = document.createDocumentFragment()