環境搭建
以javascript為基礎構建的語言,一個js的超集,可以在任何支持js的平臺中執行,ts擴展了js并且添加了類型,但是ts不能被js解析器直接執行,需要編譯器編譯為js文件,然后引入到 html 頁面使用。
ts增加了數據類型,支持es的新特性,添加了es不具備的新特性,豐富的配置選項,還有強大的開發工具。
全局安裝ts(需要node環境),?安裝后 tsc 指令可以查看是否安裝成功
npm i -g typescript
tsc xxx.ts? //編譯ts文件為js
?基本類型
需要類型聲明,指定ts中變量的類型,指定類型后,當變量賦值時,ts會自動檢查值是否符合聲明的類型,否則就報錯。如果變量的聲明和賦值是同時進行的,ts可以自動對變量進行類型檢測;除了聲明變量,也可添加類型給函數參數,對于返回的結果也可以設置類型。
let a = true //如果變量的聲明和賦值是同時進行的,ts可以自動對變量進行類型檢測。let b:number;function sum(a:number,b:number):number{return a+b;
}
類型 | 例子 | 描述 |
number | 1,-33,2.5 | 任意數字 |
string | 'hi' | 任意字符串 |
boolean | true/false | 布爾值 |
字面量 | 其本身 (let a:10,a的值只能是10,很少這么用) | 限制變量的值就是該字面量的值 |
any | * | 任意類型(相當于關閉了類型檢測) |
unknown | * | 類型安全的any |
void | 空值(undefined) | 沒有值(或undefined) |
never | 沒有值 | 不能是任何值 |
object | {name:'張三'} | 任意的js對象 |
array | [1,2,3] | 任意js數組 |
tuple | [4,5,'123'] | 元祖,ts新增類型,固定長度數組 |
enum | enum{A,B} | 枚舉,ts新增類型 |
number類型
let a:number = 6
string類型
let str:string = "hello!"
boolean類型
let str:boolean = true
字面量 類型
let a:10
a = 10 //a只能為10let b:'male'|'female' //b只能是 'male' 或者 'female'(聯合類型) 其他值會報錯
b = 'male'
b = 'female'let c:boolean|string //c可以是布爾類型或者字符串類型
c = true
c = 'hello'
any類型
可以是任意類型,相當于對該變量關閉了ts類型檢測,不設置指定類型,默認為any類型,但是any類型的值可以賦值給任意變量,不報錯,會影響其他變量類型。少用,一般多用unknown
let d:any; //可以是任意類型,相當于對該變量關閉了ts類型檢測
d = 'hello'
d = 123
d = truelet e; //不設置指定類型,默認為any類型
unknown類型
未知類型,用法與any一致,但是不同的類型依舊不可以賦值。實際上就是一個安全類型的any,不能直接賦值給其他,可以采用類型斷言的方式賦值。告訴解析器變量的實際類型。
let e:unknown;
e = 'hello'let s:string
s = e //此時報錯,因為e不是string類型//類型斷言,兩種方式都可以
s = e as string
s = <string>e
void類型
主要用于函數的無返回值,表示函數無返回值
function fn():void{}
never類型
表示永遠不會返回結果,比如調用下方的方法就會報錯,代碼執行立即結束,則沒有返回值了
function fn():never{throw new Error('報錯了')
}
?objec類型
比較雞肋,萬物皆是對象,可以是 {} ,可以是 function,也可以是[ ] 。
let a:object;
a = {}
a = function (){}//b是對象類型,并且要有一個name屬性,age屬性可有可無,再添加屬性就會報錯
let b:{name:string,age?:number};//任意字符串的屬性名,對應的值為any任意類型,可以寫多個屬性,但是一定要有name屬性
let c = {name:string,[propName:string]:any}
c = {name:'hello'age:18,gender:'男'}let d:(a:number,b:number)=>number //
d = function (a:number,b:number):number{return a + b
}
Array類型
let e:string[]; //表示字符串數組
e = ['a','b']let f:number[]; //數字數組,let g:Array<number>; // 數字數組,與上方的意義相同
g = [1,2,3,4]
元組類型
固定長度的數組,嚴格需要個數一致。
let h:[string,number]
h = ['abe',123]
enum 枚舉
enum Gender{male = 0female = 1
}
let i:{name:string,gender:Gender }
i = {name:'hello',gender:Gender.male
}
& 表示同時
let j:{name:string} & {age:number};
j = {name:'hello',age:18
}
類型別名
type myType = 1|2|3
let m:myType //起了別名
編譯選項
自動編譯文件
使用-w指令,ts會監聽文件變化,并在變化時對文件重新編譯。
tsc xxx.ts -w
自動編譯整個項目
?需要配置tsconfig.json文件,添加配置文件后,執行 tsc 指令,可以完成對整個項目的編譯
tsc -w 指令監聽并編譯整個項目文件 可以直接使用命令行來初始化配置文件
tsc -init
配置選項
include
用來指定哪些ts文件需要被編譯
{"include":["./src/**/*" //src文件夾下所有文件 **表示任意目錄,*表示任意文件]
}
exclude
用來指定哪些ts文件不需要被編譯,默認值:["node_modules",'browser_components','jspm_packages'],也可以不配置。
{"exclude": ["./src/hello/**/*"],
}
extends
定義被繼承的配置文件,另一個配置文件的配置選項和 tsconfig.json 一致。
{"extends":"./config.json",
}
files
指定被編譯文件的列表,只有需要變異的文件少時才會用到。類似于include,這個僅限于文件。
{"files": ["./src/01.ts"]
}
compilerOptions 編譯選項
target
指定ts被編譯為ES的版本,默認是 ES3
//可取值為:'es3',?'es5','es6',?'es2015','es2016','es2017',?'es2018','es2019','es2020','es2021',‘es2022','esnext'
{"compilerOptions": {"target":"ES3"}
}
module
指定要使用的模塊化的規范
//取值 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015', 'es2020', 'es2022', 'esnext', 'node16', 'nodenext'{"compilerOptions": {"module": "es6"}
}
lib
用來指定項目中要使用的第三方的庫,是一個數組,但是一般情況下我們不會去改。
//可取值 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'esnext.array', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'decorators', 'decorators.legacy'{"compilerOptions": {// "lib": ["es6"]}
}
outDir
指定編譯后的文件所在的路徑,默認編譯是和原ts文件在同一目錄下。
{"compilerOptions": {"outDir": "./dist"}
}
outFile
指定將ts代碼編譯后合并為一個js文件(默認合并的是全局作用域中的代碼),如果涉及到模塊化(export / import)會報錯,需要更改 module 為 amd 或者是 system,一般不常用。
{"compilerOptions": {"outFile": "./dist/app.js"}
}
allowJs
是否對js文件進行編譯,默認是false
{"compilerOptions": {"allowJs": false}
}
checkJs
檢查js代碼是否符合語法規范,默認是false
{"compilerOptions": {"checkJs": false}
}
?removeComments
是否移除編譯后js中的注釋。
{"compilerOptions": {"removeComments": true}
}
?noEmit
是否生成編譯后的文件,默認為false
{"compilerOptions": {"noEmit": false,}
}
noEmitOnError
當有錯誤的時候,不生成編譯文件,默認為false
{"compilerOptions": {"noEmitOnError": false,}
}
?alwaysStrict
設置編譯后的文件是否使用嚴格模式,默認為false
{"compilerOptions": {"alwaysStrict": false,}
}
?noImplicitAny
不允許 ts 中隱式 any 的類型出現,比如忘記給函數形參指定數據類型
{"compilerOptions": {"alwaysStrict": true,}
}
?noImplicitThis
不允許不明確類型的 this,默認值false
{"compilerOptions": {"noImplicitThis": true,}
}
?strictNullChecks
嚴格檢查空值 null 并且報錯,默認值為false
{"compilerOptions": {"strictNullChecks": true,}
}
?其余配置選項參考:tsconfig.json · TypeScript中文網 · TypeScript——JavaScript的超集
?
使用webpack來配置ts的打包編譯
npm init
npm i -D webpack webpack-cli typescript ts-loader html-webpack-plugin clean-webpack-plugin webpack-dev-server
webpack.config.js
const path = require('path')
const HTMLWebpackPlugin = require("html-webpack-plugin")
const { CleanWebpackPlugin } = require("clean-webpack-plugin")
module.exports = {//指定入口文件entry: "./src/index.ts",//指定打包文件的所在目錄output: {//指定打包文件目錄path: path.resolve(__dirname, 'dist'),//打包后文件名稱filename: "bunndle.js",clean: true,environment:{arrowFunction:false}},module: {rules: [//指定ts文件的loader{test: /\.ts$/,use: [{loader: "babel-loader",options: {presets: [["@babel/preset-env", {targets: { "chrome": "88","ie":"11"},"corejs": "3","useBuiltIns": "usage"}]]}},],//要排除的文件exclude: /node-modules/}]},plugins: [new HTMLWebpackPlugin({template: "./public/index.html"}),new CleanWebpackPlugin()],resolve: {extensions: [".ts", ".js"]},mode: "production"
}
//tsconfig.json{"compilerOptions":{"module": "es2015","target": "es2015","strict": true}
}
//package.json"scripts": {"test": "echo \"Error: no test specified\" && exit 1","build": "webpack","start": "webpack serve --open chrome.exe "},
Class類的一點總結
super函數調用:當子類繼承父類后,有了自己的構造函數,那么相當于父類的構造函數被重寫,那么將不會調用父類的構造函數會報錯,此時需要調用super函數來執行父類的構造函數。
abstact類:當一個類只用于繼承時,那么使用抽象類,且不能用來創建對象,抽象父類的公共方法,需要子類必須重寫抽象方法,不用寫函數體,抽象方法只能寫在抽象類中。
abstract class Parent{abstract test():void;
}class Child extends Parent{constructor(){super()}test(){console.log('test')}}
接口interface
用來定義一個類的結構,應該包含哪些屬性和方法,同時也可以當做是類型聲明,但是接口可以重復定義,最終是將相同接口的內容合并在一起。
接口可以在定義類的時候去限制類的結構,接口內的所有屬性不能有實際的值,方法也是抽象方法,可以看做是一個抽象類,通過? implements 進行實現。
interface myInterface{name:string;age:number;test():void;
}const obj:myInterface = {name:'sss',age:111}class Test implements myInterface{name:string,construcror(name:string){this.name = name}test(){}
}
屬性修飾符
public:修飾的屬性可以在任意位置訪問修改。
private:私有屬性,只能在類內部修改,如果要修改private屬性可以添加 getter setter 的方法,外部可以直接通過 . 的方式進行訪問和修改屬性。
class Test implements myInterface{private _name:stringpivate _age:numberget name(){return this._name}set name(value){this._name = value}
}let test = new Test()
let name = test.name
protected:受保護的屬性,只能在當前的類和子類中(內部)訪問,外部不能訪問。
泛型
在定義函數或類時,如果遇到類型不明確就可以使用泛型,泛型可以同時指定多個,
function fn<T>(a:T):T{return a
}
let a = fn(10) //不指定類型,ts會自動對類型進行推斷,此時T為number
let str = fn<string> ('hello') // 指定泛型function fn2<T,K>(a:T,b:K):T{return a
}
let num = fn2<number,string>(123,'hello')interface Inter{length:number
}
function fn3<T extends Inter>(a:T):number{ //繼承Inter接口,是Inter的子類return a.length
}
fne({length:10})class MyClass<T>{name:T;constructor(name:T){this.name = name}
}
const mc = new MyClass<string>('jerry')
其他參考文檔:文檔簡介 · TypeScript中文網 · TypeScript——JavaScript的超集