typescript入門(一)

typescript是什麼

  • Typescript是由微軟開發的一款開源的編程語言
  • Typescript是Javascript的超集,遵循最新的ES5/ES6規範。TypeScript擴展了Javascript語法
  • TS提供的類型系統能夠幫助咱們在寫代碼的時候提供更豐富的語法提示
  • 在建立前的編譯階段通過類型系統的檢查,就能夠避免不少線上的錯誤

TypeScript安裝和編譯

安裝

npm i typescript -g
複製代碼

安裝完後,控制檯會多一個 tsc 命令,可使用 tsc 文件名 的格式編譯 ts 文件git

初次編譯

Typescript 文件通常結尾使用 .ts 結尾typescript

建立一個 helloworld.ts 文件npm

// helloworld.ts
var a = 1;
複製代碼

編譯 helloworld.ts 文件,在命令行中輸入編程

tsc helloworld.ts
複製代碼

此時在同級目錄下會獲得一個 helloworld.js 文件,這個文件就是經過 Typescript 編譯來的json

在 Vscode 中快速編譯 Typescript

Vscode 提供一個監聽功能,不用每次修改都使用命令行編譯數組

生成配置文件

tsc --init
複製代碼

文件目錄下會生成一個 tsconfig.json 配置文件。文件中提供了不少 ts 編譯相關配置。好比編譯後的js版本、編譯後輸出位置等等數據結構

開啓監聽

Vscode菜單 => 終端 => 運行任務... => tsc監視 - tsconfig.jsonapp

mac快捷鍵: cmd + shift + B編程語言

Typescript 語法

數據類型

變量聲明的通常格式ide

// var 變量名: 數據類型 = 值
var a: boolean = true
// var 變量名: 數據類型1 | 數據類型2 = 值
var a: boolean | undefined = true
a = undefined
複製代碼

經過這種方式限制變量的類型,若是類型錯誤系統會給出相應的提示。

原始類型

js 中原始類型分爲:boolean、number、string、null、undefined、symbol

/** * 數據類型 * boolean 布爾類型 * number 數字類型 * string 字符串類型 * unll * undefined */

let married: boolean = false;
let age: number = 10;
let site: string = 'beijin'
let nation: string | null | undefined = '漢'
複製代碼

數組類型 array

let arr: number[] = [1, 2, 3]
let arr2: Array<number> = [1, 2, 3]
複製代碼

表示對象 (不是 Object 類型)

  • 限制每一次屬性的類型
  • 無關緊要的屬性用 ?
  • 若是有沒法預知的屬性,用 [propName: string]
  • 分割可使用 \n
let identity:{
  name: string,
  age: number,
  nation?: string,
  [propName: string]: any
} = {name: '張三', age: 16, ddd: 123}
複製代碼

元組類型 tuple

元組( Tuple )表示一個已知數量和類型的數組

let tupleArr: [string, number] = ['張', 5];
複製代碼

枚舉類型 enum

事先考慮某一個變量的全部的可能的值。默認狀況下,從0開始爲元素編號,固然也能夠手動賦值

普通枚舉

enum Gender {
  BOY,
  GIRL
}

console.log(`李雷是${Gender.BOY}`); // 0
console.log(`韓梅梅是${Gender.GIRL}`); // 1

enum Week {
  MONDAY = 1,
  TUESDAY = 2
}

console.log(`今天是星期${Week.MONDAY}`);
複製代碼

常數枚舉

  • 常數枚舉與普通枚舉的區別是,它會在編譯階段被刪除,而且不能包含計算成員。
  • 假如包含了計算成員,則會在編譯階段報錯
const enum Colors {
  Red,
  Yellow,
  Blue
}

const enum Color {Red, Yellow, Blue = "blue".length}; // 報錯
複製代碼

任意類型 any

any就是能夠賦值給任意類型, 使用 any 至關於放棄了 ts 類型檢查,慎用!

  • 第三方庫沒有提供類型文件時可使用any
  • 類型轉換遇到困難時
  • 數據結構太複雜難以定義
let root:any = document.getElementById('root');
root.style.color = 'red';
複製代碼

void 類型

void 表示沒有任何類型

當一個函數沒有返回值時,TS 會認爲它的返回值是 void 類型

function fn():void {
  
}
複製代碼

never 類型

never類型表示的是那些永不存在的值的類型。 例如, never類型是那些老是會拋出異常或根本就不會有返回值的函數表達式或箭頭函數表達式的返回值類型; 變量也多是 never類型,當它們被永不爲真的類型保護所約束時。

// 返回never的函數必須存在沒法達到的終點
function error(message: string): never {
    throw new Error(message);
}

// 推斷的返回值類型爲never
function fail() {
    return error("Something failed");
}

// 返回never的函數必須存在沒法達到的終點
function infiniteLoop(): never {
    while (true) {
    }
}
複製代碼

any void never 比較

  • any:任何值
  • void:不能有任何值
    • 一個沒有 return 值 或者 return 值是 undefined 的方法
  • never:永遠不會有返回值
    • 函數不會有執行結果
      • 函數報錯,沒有執行結果
      • 函數是死循環,沒有執行結果

Object 類型

object表示非原始類型,也就是除number,string,boolean,symbol,null或undefined以外的類型。

函數

函數的定義

形參和實參必須徹底同樣。好比形參有3個值,實參傳2個值就會報錯

function hello(name:string):void {
    console.log('hello',name);
}
hello('張三');
複製代碼

定義函數類型

定義一類函數類型,複用類型判斷

type GetUsernameFunction = (x:string,y:string)=>string;
let getUsername:GetUsernameFunction = function(firstName,lastName){
  return firstName + lastName;
}
複製代碼

可選參數、默認參數、剩餘參數

  • 可選參數:必須跟在必須參數後。
  • 默認參數:用 = 號連接。
  • 剩餘參數:把參數收集到一個變量裏
// 可選參數
function buildName(firstName: string, lastName?: string) {
    // ...
}
// 默認參數
function buildName2(firstName: string, lastName: string = 'sss') {
    // ...
}
// 剩餘參數
function buildName(firstName: string, ...restOfName: string[]) {
  return firstName + " " + restOfName.join(" ");
}
let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
複製代碼

函數重載

根據函數接受的參數不一樣,作不一樣的處理

let obj: any = {};
function attr(val: string): void; function attr(val: number): void; function attr(val: any): void {
    if (typeof val === 'number') {
        obj.age = val;
    } else if (typeof val === 'string') {
      obj.name = val;
  }
}
attr('zfpx');
attr(9);
attr(true); // 報錯 沒有定義 boolean 類型
console.log(obj);
複製代碼

注意:function attr(val:any): void 並非重載列表的一部分,只是寫法要求

如何定義類

class Greeter {
  // 實例的屬性
  greeting: string;
  // 構造器
  constructor(message: string) {
    this.greeting = message;
  }
  // 原形方法
  greet(): string {
    return "Hello, " + this.greeting;
  }
  // 存取器(方法在原形上,賦值的屬性在實例上)
  get greetName() {
    return this.greeting
  }
  set greetName(message: string) {
    this.greeting = message
  }
}

let greeter = new Greeter("world");
複製代碼

繼承

  • 子類繼承父類後子類的實例就擁有了父類中的屬性和方法,能夠加強代碼的可複用性
  • 將子類公用的方法抽象出來放在父類中,本身的特殊邏輯放在子類中重寫父類的邏輯
  • super能夠調用父類上的方法和屬性
class Animal {
  name: string;
  constructor(theName: string) {
    this.name = theName;
  }
  move(distanceInMeters: number = 0) {
    console.log(`${this.name} moved ${distanceInMeters}m.`);
  }
}

class Snake extends Animal {
  constructor(name: string) {
    super(name);
  }
  move(distanceInMeters = 5) {
    console.log("Slithering...");
    super.move(distanceInMeters);
  }
}

let sam = new Snake("Sammy the Python");

sam.move();
複製代碼

修飾符 public protected private readonly

修飾符默認爲 public

  • public 類裏面、子類、其它任何地方外邊均可以訪問
  • protected 類裏面、子類、均可以訪問,其它任何地方不能訪問
  • private 類裏面能夠訪問, 子類和其它任何地方都不能夠訪問
  • readonly 只讀 只讀屬性必須在聲明時或構造函數裏被初始化
class Father {
  public name: string;  //類裏面 子類 其它任何地方外邊均可以訪問
  protected age: number; //類裏面 子類 均可以訪問,其它任何地方不能訪問
  private money: number; //類裏面能夠訪問, 子類和其它任何地方都不能夠訪問
  constructor(name: string, age: number, money: number) {//構造函數
      this.name = name;
      this.age = age;
      this.money = money;
  }
  desc() {
    console.log(`${this.name} ${this.age} ${this.money}`);
  }
}
class Child extends Father{
  constructor(name: string, age: number, money: number) {
      super(name, age, money);
  }
  getName() { console.log(this.name) }
  getAge() { console.log(this.age) }
  getMoney() { console.log(this.money) } // 報錯,不能讀取
}

let child = new Child('zfpx',10,1000);
console.log(child.name);
console.log(child.age); // 報錯,不能讀取
console.log(child.money); // 報錯,不能讀取
複製代碼

靜態屬性 靜態方法 static

在類上添加屬性和方法

class Father {
  static className = 'Father';
  static getClassName() {
    return Father.className;
  }
  public name: string;
  constructor(name:string) {//構造函數
    this.name=name;
  }

}
console.log(Father.className);
console.log(Father.getClassName());
複製代碼

抽象類 abstract

對子類的限制,限制子類必須實現某些功能

  • 抽象描述一種抽象的概念,沒法被實例化,只能被繼承
  • 沒法建立抽象類的實例
  • 抽象方法不能在抽象類中實現,只能在抽象類的具體子類中實現,並且必須實現
abstract class Animal3 {
  abstract speak(): void;
}
class Cat extends Animal3{
  speak(){ // 子類必須實現
    console.log('喵喵喵');
  }
}
let Animal = new Animal(); // 報錯,抽象類不能實例
let cat = new Cat();
cat.speak();
複製代碼

接口 interface

複用約束

簡單的聲明接口

// 約束對象
interface userInterface {
  name: string,
  height: number,
}
function user(obj: userInterface):void {
  console.log(`${obj.name}: ${obj.height}`)
}
user({name: '張三', height: 170})

複製代碼

函數類型接口

對方法傳入的參數和返回值進行約束

// 約束函數
interface discount {
  (price: number): number
}
let cost: discount = function (price: number): number {
  return price * 8
}
cost(100)
複製代碼

可索引接口

對數組和對象進行約束

  • [index: number] 約束數組
  • [index: string] 約束對象
// 約束數組
interface arrInterface {
  [index: number]: string,
}
let arr: arrInterface = ['123', '333']

// 約束對象
interface objInterface {
  [index: string]: string,
}
let obj: objInterface = {name: 'ddd'}
複製代碼

類接口

限制類的屬性、方法、參數、返回值

  • 一個類能夠有多個接口
  • 接口檢查的是實例部分,靜態部分將不會檢查
interface Speakable { // 第一個接口
  name: string;
  speak(words: string): void
}
interface Bird { // 第二個接口
  fly(): void
}
class Dog implements Speakable, Bird {
  name: string;
  constructor(name: string) {
    this.name = name
  }
  speak(words: string): void {
    console.log(words);
  }
  fly(): void {}
}
let dog = new Dog('旺財');
dog.speak('汪汪汪');
複製代碼

構造函數的類型

約束構造函數的參數、實例上的屬性方法

// 類接口
interface ClockInterface {
  tick(): void;
}
// 構造函數接口
interface ClockConstructor {
  new (hour: number, minute: number): ClockInterface;
}
// 實現類
class DigitalClock implements ClockInterface {
  constructor(h: number, m: number) { }
  tick() {
    console.log("beep beep");
  }
}
// 使用構造函數接口,接受 ClockConstructor 構造函數,並返回 ClockInterface
function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
  return new ctor(hour, minute);
}
let digital = createClock(DigitalClock, 12, 17);
複製代碼

接口的繼承

接口能夠經過繼承擴展子接口

interface aaa {
  name: string
}
interface bbb extends aaa {
  age: number
}
let u: bbb = {
  name: 'sss',
  age: 123
}
複製代碼

readonly 設置接口只讀

當不但願接口上的屬性被修改時,使用 readonly

interface Person{
  readonly id: number;
  name: string
}
let tom: Person = {
  id: 1,
  name: 'zhufeng'
}
tom.id = 1; // 報錯。只讀屬性不能被修改
複製代碼

泛型

  • 泛型(Generics)是指在定義函數、接口或類的時候,不預先指定具體的類型,而在使用的時候再指定類型的一種特性
  • 泛型 T 做用域只限於函數內部使用

簡單的泛型

若是有一個函數,接受一個變量,並要求返回值與變量的類型同樣

// 通用
function identity<T>(arg: T): T { // `T` 只表示類型,不表示值
    return arg;
}
// 數組
function loggingIdentity<T>(arg: Array<T>): Array<T> {
    return arg;
}
複製代碼

類的泛型

class MyArray <T> {
  private list: T[] = [];
  add(value:T) {
    this.list.push(value);
  }
}
let arr = new MyArray();
arr.add(1)
arr.add('1')

let arr2 = new MyArray<string>(); // 固定泛型類型
arr2.add(1) // 報錯
arr2.add('1')
複製代碼

類型推論

在有些沒有明確指出類型的地方,類型推論會幫助提供類型

  • 定義時未賦值就會推論成any類型
  • 若是定義的時候就賦值就能利用到類型推論
let x = 1 // 默認爲 number
x = true // 報錯

let y // 默認爲 any
y = 1
y = true
複製代碼

包裝對象(Wrapper Object)

基礎數據類型用字面量聲明、構造函數聲明出來的是不同的。原始數據類型(字面量)調用方法時,JavaScript 會在原始數據類型和對象類型之間作一個迅速的強制性切換。

ts 中應該避免構造函數聲明

let isOK: boolean = true; // 編譯經過
let isOK: boolean = Boolean(1) // 編譯經過
let isOK: boolean = new Boolean(1); // 編譯失敗 指望的 isOK 是一個原始數據類型
複製代碼

類型斷言

尖括號語法

let someValue: any = "this is a string";

let strLength: number = (<string>someValue).length; 複製代碼

as語法

let someValue: any = "this is a string";

let strLength: number = (someValue as string).length;
複製代碼
  • 類型斷言能夠將一個聯合類型的變量,指定爲一個更加具體的類型
  • 不能將聯合類型斷言爲不存在的類型
let name5: string | number;
(name5 as number).toFixed(3);
(name5 as string).length;
(name5 as boolean);
複製代碼
相關文章
相關標籤/搜索