變量和數據類型
JavaScript雖說深受萬千程序員喜愛,卻有着對於企業大規模開發很難管理的缺陷。這時候,TypeScript的優勢便體現出來。接下來,我們會先接觸在TypeScript中定義變量相關的問題。之后再來了解JavaScript類型在TypeScript中的變化以及TypeScript中新增的類型。希望這些內容可以幫助你對typescript更加了解。
一. 變量聲明方式
1.1. 聲明變量的格式
我們已經強調過很多次,在TypeScript中定義變量需要指定 標識符 的類型。
所以完整的聲明格式如下:
var/let/const標識符: 數據類型 = 賦值;
比如我們聲明一個message,完整的寫法如下:
- 注意:這里的string是小寫的,和String是有區別的
- string是TypeScript中定義的字符串類型,String是ECMAScript中定義的一個類
letmessage:string="Hello World";"Hello TypeScript"
message =;// 正確的做法20
message =;// 錯誤的做法,因為message是一個string類型
1.2. 聲明變量的關鍵字
在TypeScript定義變量(標識符)和ES6之后一致,可以使用var、let、const來定義:
varmyname:string="abc";let
myage:number=20;const
myheight:number=1.88;
但是,我們會發現使用var關鍵字會有一個警告:

var關鍵字警告
可見,在TypeScript中並不建議再使用var關鍵字了,主要原因和ES6升級后let和var的區別是一樣的,var是沒有塊級作用域的,會引起很多的問題,這里不再展開探討。
所以,在之后的開發中,我們定義變量主要使用let和const
1.3. 變量的類型推斷
在開發中,有時候為了方便起見我們並不會在聲明每一個變量時都寫上對應的數據類型,我們更希望可以通過TypeScript本身的特性幫助我們推斷出對應的變量類型:
letmessage ="Hello World";
上面的代碼我們並沒有指定類型,但是message實際上依然是一個字符串類型:

給message賦值一個number
這是因為在一個變量第一次賦值時,會根據后面的賦值內容的類型,來推斷出變量的類型:
- 上面的message就是因為后面賦值的是一個string類型,所以message雖然沒有明確的說明,但是依然是一個string類型
letmessage ="Hello World";// string類型let
age =20;// number類型let
isFlag =true;// boolean類型
1.4. 聲明name報錯
我們在TypeScript的文件中聲明一個name(很多其他的名字也會)時,會報錯:

聲明name報錯信息
主要錯誤信息:
無法重新聲明塊范圍變量“name”
我們前面明明(明明說管我什么事)沒有聲明name,但是卻說我們重復聲明了
- 這次是因為我們的
typescript將DOM typings作為全局的運行環境; - 所以當我們聲明
name時, 與DOM中的全局name屬性出現了重名;

name的聲明位置
如何解決這個問題呢?
- 有兩種方案:去掉DOM typings 的環境和聲明模塊
方式一:刪除DOM typings的環境
但是這種辦法對於我們來說並不合適,因為我們依然希望在DOM下編譯我們的TypeScript代碼

刪除DOM typing
方式二:聲明我們的ts文件為一個模塊
既然與全局的變量出現重名,那我們將腳本封裝到模塊(module)中,因為模塊有屬於自己的作用域,就不會和全局的產生沖突:
- 在Typescript 中,我們可以使用ES6的export來導出一個對象,並且該文件被視為module
letname ="coderwhy";export
{};
1.5. console.log報錯
另外為了測試方便我們經常使用console.log來進行測試,但是使用時會報一個警告:
console.log警告
這個時候,我們可以配置

配置tslint
"no-console": false
二. JavaScript數據類型
2.1. number類型
數字類型是我們開發中經常使用的類型,TypeScript和JavaScript一樣,不區分整數類型(int)和浮點型(double),統一為number類型。
// 1.數字類型基本定義let
num =100;20
num =;6.66
num =;
如果你學習過ES6應該知道,ES6新增了二進制和八進制的表示方法,而TypeScript也是支持二進制、八進制、十六進制的表示:
// 2.其他進制表示100
num =;// 十進制0b110
num =;// 二進制0o555
num =;// 八進制0xf23
num =;// 十六進制
2.2. boolean類型
boolean類型只有兩個取值:true和false,非常簡單
// boolean類型的表示let
flag:boolean=true;false
flag =;20
flag =>30;
2.3. string類型
string類型是字符串類型,可以使用單引號或者雙引號表示:
- 注意:如果打開了TSLint,默認情況下推薦使用使用雙引號
// string類型表示let
message:string="Hello World";'Hello TypeScript'
message =;
同時也支持ES6的模板字符串來拼接變量和字符串:
constname ="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會推薦我們使用上面這種方式
constnames1:string[] = ["why","abc","cba"];const
names2:Array<string> = ["why","abc","cba"];
2.5. object類型
object對象類型可以用於描述一個對象:
// object類型表示const
myinfo: object = {"why"
name:,20
age:,1.88
height:,
};
但是上面的代碼會報一個警告:

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

關閉TSLint字母排序
"object-literal-sort-keys": false
屬性是不可以訪問的
如果我們訪問myinfo中的屬性,會發現報錯:

找不到name屬性
這是因為TypeScript並不知道某一個object類型上面就有一個name的屬性。
但是如果我們讓它是類型推斷的,就可以正常的訪問:
- 這是因為推導出來的類型,是如下的類型

myinfo的類型
還有一種方法是定義后面會學到的接口,TypeScript一個非常好用的特性就是接口interface,后續我們會進行非常詳細的學習
2.6. symbol類型
在ES5中,如果我們是不可以在對象中添加相同的屬性名稱的,比如下面的做法:
constperson = {"程序員"
identity:,"老師"
identity:,
}
通常我們的做法是定義兩個不同的屬性名字:比如identity1和identity2。
但是我們也可以通過symbol來定義相同的名稱,因為Symbol函數返回的是不同的值:
consts1 = Symbol("identity");const
s2 = Symbol("identity");const
person = {"程序員"
[s1]:,"老師"
[s2]:,
};
這是Symbol的一個用法,更多其他用法大家可以自行學習,或者等到后續確實需要用到時,我們再詳細講解。
2.7. null和undefined
在JavaScript 中,undefined 和null 是兩個基本數據類型。
在TypeScript中,它們各自的類型也是undefined和null,也就意味着它們既是實際的值,也是自己的類型:
constn:null=null;const
u:undefined=undefined;
三. TypeScript數據類型
TypeScript在原有的JavaScript基礎上引入了很多好用的類型:enum枚舉類型、tuple元組類型、any類型、void類型、never類型等
3.1. enum類型
3.1.1. 枚舉的基本定義
枚舉類型在很多語言都有的類型,比如C++、Java等等,並且也非常好用,所以TypeScript引入了enum類型,讓我們開發更好的方便和安全。
枚舉類型通常是定義一組數據:
enumDirection {const
EAST,
WEST,
NORTH,
SOUTH,
}
d1 = Direction.EAST;const
d2 = Direction.NORTH;
3.1.2. 枚舉類型的值
枚舉類型有自己的值,比如打印上面的d1和d2

打印d1和d2結果
默認情況下,枚舉中的數據是從0開始的,我們可以改變它的初始化值,比如下面的代碼:
enumDirection {10
EAST =,const
WEST,
NORTH,
SOUTH,
}
d1 = Direction.EAST;const
d2 = Direction.NORTH;console
.log(d1);// 10console
.log(d2);// 12
也可以全部自己來指定:
enumDirection {10
EAST =,20
WEST =,30
NORTH =,40
SOUTH =,const
}
d1 = Direction.EAST;const
d2 = Direction.NORTH;console
.log(d1);// 10console
.log(d2);// 30
我們也可以通過對應的值去獲取對應的數據名稱:
console.log(Direction[10]);// EASTconsole
.log(Direction[30]);// NORTH
3.2. tuple類型
3.2.1. tuple的基本使用
tuple是元組類型,很多語言中也有這種數據類型,比如Python、Swift等。
consttInfo: [string,number,number] = ["why",18,1.88];const
item1 = tInfo[0];// why, 並且知道類型是string類型const
item2 = tInfo[1];// 18, 並且知道類型是number類型
3.2.1. tuple和數組類比
初學tuple會覺得它和數組非常相似
但是數組中通常會定義一組相同的數據,如果數據不同會造成類型的丟失:
- 注意:這里我使用了一種聯合類型,后面會講到
constaInfo:Array<string|number> = ["why",18,1.88];const
itema = aInfo[0];// why,但是並不知道itema是string類型還是number類型
3.3. any類型
在某些情況下,我們確實無法確定一個變量的類型,並且可能它會發生一些變化,這個時候我們可以使用any類型(類似於Dart語言中的dynamic類型)
leta:any="why";123
a =;true
a =;const
aArray:any[] = ["why",18,1.88];
3.4. void類型
void類型通常用於函數沒有返回值時來使用:
- 首先我們需要說明的是,在TypeScript中函數也是有類型的
下面的函數,雖然我們沒有指定它的類型,但是它會通過類型推導出來:
constsum =(num1: number, num2: number) =>{return
num1 + num2;// 相當於下面的寫法
};
const
sum:(num1: number, num2: number) =>number=(num1: number, num2: number) =>{return
num1 + num2;
};

sum函數的類型
如果一個函數沒有返回值,那么它的返回值類型就是void
- 我們可以將null和undefined賦值給void類型,也就是函數可以返回null或者undefined
constsayHello:(name: string) =>void=(name: string) =>{console
.log("hello "+ name);
};
3.5. never類型
never類型表示一種從來不會存在的值的類型,有點繞,我們來這樣理解:
- 如果一個函數中是一個死循環,那么這個函數會返回東西嗎?不會,那么寫void類型或者其他類型作為返回值類型都不合適,我們就可以使用never類型。
- 如果一個函數是拋出一個異常,那么這個函數是不是也沒有返回值呢?這個時候我們也可以使用never類型。


死循環的函數拋出異常的函數
最后我想說的是,變量及數據類型猶如在茫茫TS宇宙中的一顆行星,想要更加深入了解TS,光看這些是遠遠不夠的,如果你對此有興趣,接下來我會分享更多關於TS的內容,當然你也可以自行研究,希望這些內容可以幫你在編程道路上更進一步。
