一、安裝使用
1⃣️npm install typescript -g; // 安裝typescript
2⃣️初始化項目: 進入項目文件夾後:npm init -y 生成package.json文件;
3⃣️tsc --init,創建tsconfig.json文件,這是ts項目的配置文件,可以設置ts的編譯參數;
4⃣️安裝@types/node模塊:主要用來解決模塊聲明問題;
5⃣️創建編寫ts後綴文件,VSCode-任務-運行生成任務-構建,將ts文件轉換爲js文件; // 或直接在cmd中運行 tsc ts文件名,來編譯ts文件;
6⃣️在vue中使用(先將webpack升級到4版本(如果不是報錯參考:https://blog.csdn.net/qq_25243451/article/details/80331269)):
1、vue-cli創建項目之後:安裝編譯器 ts-loader: npm i ts-loader -D;
2、然後去webpack.base.conf.js文件中配置:
extensions: ['.js', '.vue', '.json', '.ts']
和
{
test: /\.ts$/,
loader: 'ts-loader',
options: {
appendTsSuffixTo: [/\.vue$/],
}
},
3、修改tsconfig.json文件,一下列出我自己的配置(初學)
{
// "compileOnSave": true, // 可以讓ide在保存文件時根據tsconfig.json重新生成文件
"compilerOptions": {
/* Basic Options */
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
"module": "esnext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
// "lib": [], /* 編譯過程中需要引入的庫文件的列表. */
"allowJs": true, /* 允許編譯js文件. */
// "checkJs": true, /* 在js文件中報告錯誤,需與allowJs配合使用. */
"jsx": "preserve", /* 在.tsx文件中支持JSX: 'preserve', 'react-native', or 'react'. */
// "declaration": true, /* 生成相應的 '.d.ts' 文件. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
"sourceMap": true, /* Generates corresponding '.map' file. */
"pretty": true,
// "outFile": "./", /* 將輸出文件合併爲一個文件. */
// "outDir": "./", /* 重定向輸出目錄. */
// "rootDir": "./", /*僅用來控制輸出目錄結構 - - outDir. */
// "composite": true, /* Enable project compilation */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": true, /* 在表達式和聲明上有隱含 'any' 類型時報錯. */
// "strictNullChecks": true, /* 在嚴格的null檢查模式下,null和undefined值不包含在任何類型裏,只允許它們自己和any來賦值. */
"strictFunctionTypes": true, /* 禁用函數參數雙向協變檢查. */
// "strictPropertyInitialization": true, /* 確保類的非undefined屬性已經在構造函數裏初始化,與strictNullChecks同時使用. */
// "noImplicitThis": true, /* 當'this'表達式的值爲any類型的時候生成一個錯誤. */
// "alwaysStrict": true, /* 以嚴格模式解析併爲每個源文件生成 "use strict"語句. */
/* Additional Checks */
// "noUnusedLocals": true, /* 若有未使用的局部變量則報錯. */
// "noUnusedParameters": true, /* 若有未使用的參數則報錯. */
// "noImplicitReturns": true, /* 不是函數的所有返回路徑都有返回值時報錯. */
// "noFallthroughCasesInSwitch": true, /* 報告switch語句的fallthrough錯誤(即,不允許switch的case語句貫穿). */
/* Module Resolution Options */
"moduleResolution": "node", /* 'node' (Node.js) or 'classic' 決定如何處理模塊. */
// "baseUrl": "./", /* 解析非相對模塊名的基準目錄. */
// "paths": {}, /* 模塊名基於'baseUrl'的路徑映射的列表. */
// "rootDirs": [], /* 根文件夾列表,表示運行時組合工程結構的內容. */
"typeRoots": [ /* 要包含的類型聲明文件路徑列表. */
"node_modules/@types",
"./types"
],
"types": [ /* 要包含的類型聲明文件名列表. */
"node"
],
"allowSyntheticDefaultImports": true, /* 允許從沒有設置默認到處的模塊中默認導入. */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* 不把符號鏈接解析爲其真實路徑;將符號鏈接文件視爲真正的文件. */
/* Source Map Options */
// "sourceRoot": "", /* 指定TypeScript源文件的路徑,以便調試器定位。當TypeScript文件的位置是在運行時指定使用此標記,路徑信息會被加到sourceMap裏. */
// "mapRoot": "", /* 爲調試器制定sourcemap文件的路徑,而不是使用生成時的路徑。當.map文件是在運行時制定的,並不同與js文件的地址時使用實這個標記,路徑會被嵌入到sourceMap中. */
// "inlineSourceMap": true, /* 生成單個sourcemaps文件,而不是將每sourcemaps生成不同的文件. */
// "inlineSources": true, /* 將代碼與sourcemaps生成到一個文件中,與 '--inlineSourceMap' or '--sourceMap' 同時使用. */
/* Experimental Options */
// "experimentalDecorators": true, /* 啓用實驗性的es裝飾器. */
// "emitDecoratorMetadata": true, /* 給源碼裏的裝飾器聲明買啥概念設計類型元數據. */
},
/* 如果"files"和"include"都沒有被指定,編譯器默認包含當前目錄和子目錄下所有的TypeScript文件(.ts, .d.ts 和 .tsx),排除在"exclude"裏指定的文件 */
"files": [ // 需要編譯的文件
"types/index.d.ts"
],
"include" : [ // 包含的某個路徑下的文件
"src/**/*",
"src/*"
],
"exclude": [ // 拒絕某些路徑下的文件
"node_modules"
]
}
4、修改main.js文件
把項目主文件main.js
修改成main.ts
,裏面的寫法基本不變,但是有一點需要注意:
引入Vue文件的時候需要加上.vue
後綴,否則編輯器識別不到;把webpack的entry文件也修改成main.ts
5、TypeScript並不支持Vue文件,所以需要告訴TypeScript*.vue
文件交給vue編輯器來處理。在根目錄創建一個types文件加然後在其下,創建index.d.ts文件,(也可以在src目錄中創建,次文件需要到tsconfig.json>>files中引入編譯) 文件內容爲
declare module "*.vue" {
import Vue from 'vue'
export default Vue
}
6、到此一般沒什麼問題,npm run dev 就可以運行。
7、到這一步告訴你一個消息。如果用vue-cli3.0版本,以上無需配置就能運行。
二、基礎類型
let flag : boolean = false // 布爾
let age : number = 666 // 數字 // ts還支持二進制和八進制
let name : string = "二狗子" // 字符串
let attr = `小狗`
let desc : string = `${name}是一隻${attr}`
let list : number[] = [1, 2, 3] // 數組 // 表示由此類型組成的數組
let list1 : Array<number> = [1, 2, 3] // 泛型數組
// Null和Undefined
let u : undefined = undefined
let n : null = null
/* Any */
/* 當在編程階段還不知道定義什麼類型的時候,就可以用Any類型,它可以讓值直接通過編譯階段 */
// TypeScript友好的爲我們提供了一種特殊的類型any,比如我們在程序中不斷變化着類型,又不想讓程序報錯,這時候就可以使用any了
let notSure: any = 4;
notSure = "string";
notSure = true;
/* Void */
// 它不表示任何一個類型
function warnUser(): void { // 當一個函數沒有返回值時
console.log("This is void message");
}
// 聲明一個void類型的變量只能爲它賦予undefined和null
let unusable: void = undefined;
/* 元組Tuple */
/* 元組類型允許表示一個已知元素數量和類型的數組,各元素的類型不必相同。 */
let x: [string, number];
x = ['hello', 10]; // OK
x = [10, 'hello']; // Error
/*枚舉*/
enum Direction { // 默認情況下從0開始 // 此處Up值爲1,Right爲2
Up = 1,
Right,
Down,
Left
}
let a: Direction = Direction.Right
console.log(a) // 2
enum Direction1 { // Up值爲0,Right爲1
Up,
Right,
Down,
Left
}
let b: Direction1 = Direction1.Up
console.log(b) // 0
/* Never */
/* never類型表示的是那些用不存在的值的類型;它可以賦值給任何類型,但是任何類型都不能賦值給never */
function error (message: string) : never {
throw new Error(message)
}
三、接口
// 接口
interface LabelledValue { // 它代表有個label屬性且類型爲string的對象
label: string
}
function printLabel (labelledObj: LabelledValue) {
console.log(labelledObj.label)
}
let myObj = {size: 10, label: "Size 10 Object"} // 可以傳入很多參數,但是必須包含一個label屬性且類型爲string的
let obj1: LabelledValue = {label: "Size 10 Object"} // 如果將其定義爲LabelledValue類型的數據,那麼該對象所包含的屬性必須跟定義好的接口完全一致
printLabel(myObj)
printLabel(obj1)
//可選屬性
interface Person {
name?: string
age?: number
}
function createSquare (config: Person): {color: string; area: number} {
let newSquare = {color: "white", area: 100}
if (config.color) {
newSquare.color = config.color
}
if (config.width) {
newSquare.area = config.width * config.width
}
return newSquare
}
let mySquare = createSquare({color: "black"})
/* 好處一:可以對可能存在的屬性進行預定義;
好處二:可以捕獲引用了不存在的屬性時的錯誤 */
// 只讀屬性
interface Point { // 一些對象屬性只能在對象剛剛創建的時候修改其值,用readonly來指定只讀屬性
readonly x: number
readonly y: number
}
let p1: Point = {x: 10, y: 20}
p1.x = 5; // error
// 類類型 實現接口
interface ClockInterface {
currentTime: Date
setTime(d: Date) // 在接口中描述一個方法,在類裏實現它
}
class Clock impolements ClockInterface { // 接口描述了類的公共部分,而不是公共和私有兩部分。它不會檢查類是否具有某些私有成員
currentTime: Date
setTime(d: Date) {
this.currentTime = d
}
constructor(h: number, m: number)
}
// 繼承接口 一個接口可以繼承多個接口
interface Shape {
color: string
}
interface PenStroke {
penWidth: number
}
interface Square extends Shape, PenStroke {
sideLength: number
}
let square = <Square> {} // 創建一個對象並指定泛型
square.color = "blue"
square.penWidth = 5;
square.sideLength = 10;
// 混合類型 所謂混合類型就是在一個接口中定義多種類型,比如屬性,函數,數組等
interface Counter {
(start: number): string
interval: number
restet(): void
}
function getCounter(): Counter {
let counter = <Counter> function (start: number) {}
counter.interval = 123
counter.reset = function () {}
return counter
}
let c = getCounter()
c(10)
c.reset()
c.interval = 5
四、類
class Greeter {
public greeting: string // 設置greeting屬性
public constructor (name: string) {
console.log(name)
this.greeting = name
}
public greet () {
return "Hello" + this.greeting
}
protected emp () {
console.log(`我會被繼承`)
}
}
let greeter = new Greeter("world!")
/* 修飾符
1、public 默認。類似C#中的public,指定成員可見的意思
2、private 指定它不能在聲明它的類的外部訪問(子類也不能),就是不能被繼承
3、protected 與private類似,但是在子類可以訪問,可以被繼承
4、readonly 設置爲只讀屬性。只讀屬性必須在聲明時或構造函數裏被初始化。
5、static 靜態屬性。存在於類本身上,而不是類的實例上,所以訪問的時候需要加該類名
6、abstract 抽象類。不會被實例化,僅提供繼承;用於定義抽象類和在抽象類內部定義抽象方法。
*/
class Employee extends Greeter {
code: String
constructor (name: String, code: String) { // 表明實例化時必須傳2個參數
super(name) // 調用父類構造函數
this.code = code
}
work () {
super.emp() // 調用父類的emp方法
this.doWork() // 調用當前類的方法
}
private doWork () { // 將其定義爲私有屬性,外部不能調用
console.log("這玩意兒是私有的")
}
}
let employee = new Employee('二狗子', '14')
employee.doWork() // 會報錯,私有屬性不能在外部訪問