TypeScript初步學習

一、安裝使用

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() // 會報錯,私有屬性不能在外部訪問

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章