TypeScript(三)定義變量和數據類型

一. 變量聲明方式

1.1. 聲明變量的格式

我們已經強調過很多次,在TypeScript中定義變量需要指定 標識符 的類型。

所以完整的聲明格式如下:

var/let/const 標識符: 數據類型 = 賦值;

比如我們聲明一個message,完整的寫法如下:  ,,,,,,,,,,,,,,

  • 注意:這裏的string是小寫的,和String是有區別的

  • string是TypeScript中定義的字符串類型,String是ECMAScript中定義的一個類

let message: string = "Hello World";

message = "Hello TypeScript"; // 正確的做法
message = 20; // 錯誤的做法,因爲message是一個string類型

1.2. 聲明變量的關鍵字

在TypeScript定義變量(標識符)和ES6之後一致,可以使用var、let、const來定義:

var myname: string = "abc";
let myage: number = 20;
const myheight: number = 1.88;

但是,我們會發現使用var關鍵字會有一個警告:

可見,在TypeScript中並不建議再使用var關鍵字了,主要原因和ES6升級後let和var的區別是一樣的,var是沒有塊級作用域的,會引起很多的問題,這裏不再展開探討。

所以,在之後的開發中,我們定義變量主要使用let和const

1.3. 變量的類型推斷

在開發中,有時候爲了方便起見我們並不會在聲明每一個變量時都寫上對應的數據類型,我們更希望可以通過TypeScript本身的特性幫助我們推斷出對應的變量類型:

let message = "Hello World";

上面的代碼我們並沒有指定類型,但是message實際上依然是一個字符串類型:

這是因爲在一個變量第一次賦值時,會根據後面的賦值內容的類型,來推斷出變量的類型:

  • 上面的message就是因爲後面賦值的是一個string類型,所以message雖然沒有明確的說明,但是依然是一個string類型

let message = "Hello World"; // string類型
let age = 20; // number類型
let isFlag = true; // boolean類型

1.4. 聲明name報錯

我們在TypeScript的文件中聲明一個name(很多其他的名字也會)時,會報錯:

主要錯誤信息:

無法重新聲明塊範圍變量“name”

我們前面明明(明明說管我什麼事)沒有聲明name,但是卻說我們重複聲明瞭

  • 這次是因爲我們的typescript 將 DOM typings 作爲全局的運行環境;

  • 所以當我們聲明 name時, 與 DOM 中的全局  name 屬性出現了重名;

如何解決這個問題呢?

  • 有兩種方案:去掉 DOM typings 的環境和聲明模塊

方式一:刪除DOM typings的環境

但是這種辦法對於我們來說並不合適,因爲我們依然希望在DOM下編譯我們的TypeScript代碼

方式二:聲明我們的ts文件爲一個模塊

既然與全局的變量出現重名,那我們將腳本封裝到模塊(module)中,因爲模塊有屬於自己的作用域,就不會和全局的產生衝突:

  • 在 Typescript 中,我們可以使用ES6的export來導出一個對象,並且該文件被視爲 module

let name = "coderwhy";

export {};

1.5. console.log報錯

另外爲了測試方便我們經常使用console.log來進行測試,但是使用時會報一個警告:

console.log警告

這個時候,我們可以配置

"no-console": false

二. JavaScript數據類型

2.1. number類型

數字類型是我們開發中經常使用的類型,TypeScript和JavaScript一樣,不區分整數類型(int)和浮點型(double),統一爲number類型。

// 1.數字類型基本定義
let num = 100;
num = 20;
num = 6.66;

如果你學習過ES6應該知道,ES6新增了二進制和八進制的表示方法,而TypeScript也是支持二進制、八進制、十六進制的表示:

// 2.其他進製表示
num = 100; // 十進制
num = 0b110; // 二進制
num = 0o555; // 八進制
num = 0xf23; // 十六進制

2.2. boolean類型

boolean類型只有兩個取值:true和false,非常簡單

// boolean類型的表示
let flag: boolean = true;
flag = false;
flag = 20 > 30;

2.3. string類型

string類型是字符串類型,可以使用單引號或者雙引號表示:

  • 注意:如果打開了TSLint,默認情況下推薦使用使用雙引號

// string類型表示
let message: string = "Hello World";
message = 'Hello TypeScript';

同時也支持ES6的模板字符串來拼接變量和字符串:

const name = "why";
const age = 18;
const height = 1.88;

const info = `my name is ${name}, age is ${age}, height is ${height}`;
console.log(info);

2.4. array類型

數組類型的定義也非常簡單,有兩種方式:

  • 但是TSLint會推薦我們使用上面這種方式

const names1: string[] = ["why", "abc", "cba"];
const names2: Array<string> = ["why", "abc", "cba"];

2.5. object類型

object對象類型可以用於描述一個對象:

// object類型表示
const myinfo: object = {
  name: "why",
  age: 20,
  height: 1.88,
};

但是上面的代碼會報一個警告:

這是因爲TSLint建議我們所有的key按照字母進行排序,但是這個並不是特別有必要,我們還是可以關閉掉:

"object-literal-sort-keys": false

屬性是不可以訪問的

如果我們訪問myinfo中的屬性,會發現報錯:

這是因爲TypeScript並不知道某一個object類型上面就有一個name的屬性。

但是如果我們讓它是類型推斷的,就可以正常的訪問:

  • 這是因爲推導出來的類型,是如下的類型

還有一種方法是定義後面會學到的接口,TypeScript一個非常好用的特性就是接口interface,後續我們會進行非常詳細的學習

2.6. symbol類型

在ES5中,如果我們是不可以在對象中添加相同的屬性名稱的,比如下面的做法:

const person = {
  identity: "程序員",
  identity: "老師",
}

通常我們的做法是定義兩個不同的屬性名字:比如identity1和identity2。

但是我們也可以通過symbol來定義相同的名稱,因爲Symbol函數返回的是不同的值:

const s1 = Symbol("identity");
const s2 = Symbol("identity");

const person = {
  [s1]: "程序員",
  [s2]: "老師",
};

這是Symbol的一個用法,更多其他用法大家可以自行學習,或者等到後續確實需要用到時,我們再詳細講解。

2.7. null和undefined

在 JavaScript 中,undefined 和 null 是兩個基本數據類型。

在TypeScript中,它們各自的類型也是undefined和null,也就意味着它們既是實際的值,也是自己的類型:

const n: null = null;
const u: undefined = undefined;

三. TypeScript數據類型

3.1. enum類型

3.1.1. 枚舉的基本定義

枚舉類型在很多語言都有的類型,比如C++、Java等等,並且也非常好用,所以TypeScript引入了enum類型,讓我們開發更好的方便和安全。

枚舉類型通常是定義一組數據:

enum Direction {
  EAST,
  WEST,
  NORTH,
  SOUTH,
}

const d1 = Direction.EAST;
const d2 = Direction.NORTH;

3.1.2. 枚舉類型的值

枚舉類型有自己的值,比如打印上面的d1和d2

默認情況下,枚舉中的數據是從0開始的,我們可以改變它的初始化值,比如下面的代碼:

enum Direction {
  EAST = 10,
  WEST,
  NORTH,
  SOUTH,
}

const d1 = Direction.EAST;
const d2 = Direction.NORTH;

console.log(d1); // 10
console.log(d2); // 12

也可以全部自己來指定:

enum Direction {
  EAST = 10,
  WEST = 20,
  NORTH = 30,
  SOUTH = 40,
}

const d1 = Direction.EAST;
const d2 = Direction.NORTH;

console.log(d1); // 10
console.log(d2); // 30

我們也可以通過對應的值去獲取對應的數據名稱:

console.log(Direction[10]); // EAST
console.log(Direction[30]); // NORTH

3.2. tuple類型

3.2.1. tuple的基本使用

tuple是元組類型,很多語言中也有這種數據類型,比如Python、Swift等。

const tInfo: [string, number, number] = ["why", 18, 1.88];
const item1 = tInfo[0]; // why, 並且知道類型是string類型
const item2 = tInfo[1]; // 18, 並且知道類型是number類型

3.2.1. tuple和數組類比

初學tuple會覺得它和數組非常相似

但是數組中通常會定義一組相同的數據,如果數據不同會造成類型的丟失:

  • 注意:這裏我使用了一種聯合類型,後面會講到

const aInfo: Array<string|number> = ["why", 18, 1.88];
const itema = aInfo[0]; // why,但是並不知道itema是string類型還是number類型

3.3. any類型

在某些情況下,我們確實無法確定一個變量的類型,並且可能它會發生一些變化,這個時候我們可以使用any類型(類似於Dart語言中的dynamic類型)

let a: any = "why";
a = 123;
a = true;

const aArray: any[] = ["why", 18, 1.88];

3.4. void類型

void類型通常用於函數沒有返回值時來使用:

  • 首先我們需要說明的是,在TypeScript中函數也是有類型的

下面的函數,雖然我們沒有指定它的類型,但是它會通過類型推導出來:

const sum = (num1: number, num2: number) => {
  return num1 + num2;
};

// 相當於下面的寫法
const sum: (num1: number, num2: number) => number = (num1: number, num2: number) => {
  return num1 + num2;
};

如果一個函數沒有返回值,那麼它的返回值類型就是void

  • 我們可以將null和undefined賦值給void類型,也就是函數可以返回null或者undefined

const sayHello: (name: string) => void = (name: string) => {
  console.log("hello " + name);
};

3.5. never類型

never類型表示一種從來不會存在的值的類型,有點繞,我們來這樣理解:

  • 如果一個函數中是一個死循環,那麼這個函數會返回東西嗎?不會,那麼寫void類型或者其他類型作爲返回值類型都不合適,我們就可以使用never類型。

  • 如果一個函數是拋出一個異常,那麼這個函數是不是也沒有返回值呢?這個時候我們也可以使用never類型。

死循環的函數

拋出異常的函數

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