1赡勘、TypeScript 環(huán)境安裝與運(yùn)行
Typescript中文文檔: https://typescript.bootcss.com/functions.html
1.1 TypeScript 環(huán)境安裝
全局安裝 TypeScript : npm install -g typescript
校驗(yàn) TypeScript是否安裝成功: tsc -v
tsc的作用:負(fù)責(zé)將 ts 代碼 轉(zhuǎn)為 游覽器 和 nodejs 識(shí)別的 js代碼
1.2 TypeScript 運(yùn)行
- 在后綴名為
的文件中書寫 typescript 代碼
- 使用 tsc 將 typescript 代碼編譯成 js 代碼
- 在游覽器或者 nodejs 中執(zhí)行 js 代碼
image.png
自動(dòng)編譯
1、運(yùn)行 tsc --init 嘱么,創(chuàng)建 tsconfig.json 文件
2狮含、修改 tsconfig.json 文件顽悼,設(shè)置 js 文件夾:"outDir": "./js/"
3曼振、設(shè)置 vscode 監(jiān)視任務(wù)
image.png
ts和 js的區(qū)別
ts提供了更豐富的語(yǔ)法提示;
ts在編譯階段能夠檢查錯(cuò)誤;? js是在執(zhí)行階段才檢查的錯(cuò)誤;
ts是靜態(tài)類型;? js是動(dòng)態(tài)類型;
js
let test = "123"
test = 123 // js動(dòng)態(tài)類型,可以隨意改變變量類型蔚龙,這里就把string類型改成了number類型
ts
let test = "123"
test = 123 -------這行代碼會(huì)報(bào)錯(cuò)冰评,警告:不能將類型“number”分配給類型“string”。
數(shù)據(jù)類型
JS數(shù)據(jù)類型
原始數(shù)據(jù)類型: boolean string number null undefined symbol
引用數(shù)據(jù)類型:object
TS數(shù)據(jù)類型
基礎(chǔ)類型:boolean string number null undefined symbol any never void
接口: interface
數(shù)組 number[] string[] boolean[] 泛型的寫法: Array<number>
新的語(yǔ)法特性:
as 斷言
class (OOP 面向?qū)ο蟮娜筇匦?︰封裝木羹,繼承甲雅,多態(tài);
2解孙、TypeScript 變量與數(shù)據(jù)類型
在 javaScript 弱類型語(yǔ)言,在申明變量時(shí)直接賦值就行抛人,當(dāng) JS 引擎 運(yùn)行的時(shí)候弛姜,會(huì)根據(jù)等號(hào)后面的值自動(dòng)給變量賦值對(duì)應(yīng)的類型
let 變量名 = 值;
let name = "zhangsan"; //默認(rèn)為 String 類型
let num = 18;//默認(rèn)為 Number 類型
ley obj = {};//默認(rèn)為 Object 類型
而在 typeScript 中妖枚,變量申明時(shí)必須指定變量類型廷臼,一旦為變量指定類型后,就只能給這個(gè)變量設(shè)置相同類型的值
typeScript中聲明變量時(shí)绝页,在變量名后面加上一個(gè)冒號(hào)荠商,再加上變量類型就行了。
let 變量名: 變量類型 = 值续誉;
let name: string = "張三";
let num: number = 18;
image.png
TypeScript 數(shù)據(jù)類型 | 常見類型莱没,聲明時(shí)需要指定變量類型(語(yǔ)法如下)
//1、字符串類型 '' 酷鸦、 "" 饰躲、 ``
let aName: string = "秀兒";
// 2、數(shù)值類型
let aAge: number = 18;
aAge = 18.5;
aAge = -18;
// 3臼隔、布爾值類型 true / false
let isDog: boolean = true;
isDog = false;
// 4属铁、undefined 和 null
let undef: undefined = undefined;
let nul: null = null;
TypeScript 數(shù)據(jù)類型 | 字面量,限制變量的值就是 字面量的值 本身(語(yǔ)法如下)
let num: 10;
num只能等于 10躬翁,num如果賦值11的話會(huì)報(bào)錯(cuò)
num = 10焦蘑;
let gender: ""mela" | "person";如果聯(lián)合申明的話
這個(gè) gender變量的值可以是 mela,也可以是 person盒发,但不能等于別的值
gender = "mela";
我們可以給類型取個(gè)別名例嘱,在給變量設(shè)置類型的時(shí)候,賦值類型別名就行宁舰,語(yǔ)法如下
type 類型別名 = 類型;
TypeScript 數(shù)據(jù)類型 | object
缺點(diǎn):如果只給變量指定 object 類型的話拼卵,由于 js 萬(wàn)物皆對(duì)象,變量設(shè)置 object 類型卻沒有給變量添加什么限制(例如)
oject 表示非原始類型
let obj: object;
obj = {};
obj = function(){};
obj = new Date();
obj = new Array();
obj = [];
我們一般限制對(duì)象類型的時(shí)候不是為了限制他是不是一個(gè)對(duì)象蛮艰,而是為了限制對(duì)象的屬性腋腮,所以在TS中一般不使用 object 聲明變量,而是用 {} 來(lái)指定對(duì)象中可以包含那些屬性壤蚜,語(yǔ)法如下
語(yǔ)法:{ 屬性名: 屬性值, 屬性名: 屬性值 };
通過對(duì)象的屬性限制對(duì)象
在屬性名后面加上問號(hào)即寡,表示是可選可不選屬性(以下兩種對(duì)象賦值都不會(huì)出錯(cuò),但是如果沒有問號(hào)袜刷,第一種方式會(huì)報(bào)錯(cuò))
let obj01: { name: string, age?: number };
obj01 = { name: "LBipanda" };第一種
obj01 = { name: "LBipanda", age: 18 };
但是這樣會(huì)有一個(gè)缺點(diǎn)聪富,每次聲明變量你都要已知對(duì)象的有多少屬性,如果不確定對(duì)象有多少屬性著蟹,可以使用以下方法
[propName: string]: any 代表任意類型和數(shù)量的屬性墩蔓,如下梢莽,你可以寫 age,height
propName 只是一個(gè)變量名奸披,你寫什么都行 例如 xxx昏名、a、b
let myself: { name: string, [propName: string]: any};
myself = { name: "LBipanda", age: 18, height: 178 };
還有一個(gè)業(yè)務(wù)場(chǎng)景阵面,有一個(gè)變量 d葡粒,我需要他是一個(gè)函數(shù),并且限制他的的參數(shù)類型和數(shù)量和返回值
設(shè)置函數(shù)結(jié)構(gòu)的類型聲明膜钓,語(yǔ)法如下
語(yǔ)法:(形參: 類型, 形參: 類型, ...) => 返回值類型
如果不想限制形參類型和數(shù)量的話可以這樣
語(yǔ)法:(形參: 類型, 形參: 類型, ...形參: any[]) => 返回值類型
限制了形參類型和數(shù)量
let a: (a: number, b: number) => number;
a = function(height: number, weight: number): number{
return height * weight;
}
console.log(a(10,20)) ==》打印值 200
不限制形參類型和數(shù)量
let func: (...xxx: any[]) => string;
func = function(name: string, age: number, alone: boolean): string{
let tempAlone = alone?"孤獨(dú)":"不孤獨(dú)";
return "姓名:" + name + ", 年齡:" + age + "歲嗽交,是否孤獨(dú):" + tempAlone;
}
console.log(func("李彬", 18, true))
TypeScript 數(shù)據(jù)類型 | 數(shù)組,聲明時(shí)需要指定 (語(yǔ)法如下)
特點(diǎn):
1颂斜、元素類型 固定
2夫壁、長(zhǎng)度不限制
方式一: let 數(shù)組名: 類型[];
let arr1: string[] = [ "亞瑟王", "魯班", "大喬" ];
let arr2: (string | number)[] = [ "亞瑟王", 22, "大喬", 999]
方式二:let 數(shù)組名: Array<類型>;
let arr3: Array<string> = [ "亞瑟王", "魯班", "大喬" ];
let arr4: Array<(string | number)> = [ "張三", 55, "王五", 999]
TypeScript 數(shù)據(jù)類型 | 元組(tuple)
概念:就是一個(gè)規(guī)定了 的 "數(shù)組" 而每個(gè)元素的類型,可以不相同
特點(diǎn):
1沃疮、聲明時(shí)盒让,要指定元素個(gè)數(shù)
2、聲明時(shí)司蔬,要為每個(gè)元素規(guī)定 類型
為什么要有元組邑茄?
TS 中數(shù)組元素類型必須一致,如需要不同元素俊啼,可以用 了肺缕!
理解:元組(tuple):就是一個(gè)已知的數(shù)組,內(nèi)部的元素類型 不必相同授帕。(語(yǔ)法如下)
let 元組名: [類型1, 類型2, 類型3] = [ 值1, 值2, 值3 ];
let tup1: [string, number, boolean];
tup1 = ["LBipanda", 18, true];
//訪問 元組 中的元素 和長(zhǎng)度同木,還是和 js 一樣,通過 [下標(biāo)]的方式獲取元組的元素跛十,通過.length的方式獲取元組長(zhǎng)度
console.log(tup1[0]);
console.log(tup1.length);
TypeScript 數(shù)據(jù)類型 | 枚舉(enum)
枚舉(enum):用一組標(biāo)識(shí) 來(lái)代表 數(shù)值彤路。
枚舉項(xiàng):一般用英文和數(shù)字,而 枚舉值 用整型數(shù)字
申明語(yǔ)法 枚舉名首字母要大寫
enum 枚舉名{
枚舉項(xiàng)1 = 枚舉值1,
枚舉項(xiàng)2 = 枚舉值2,
枚舉項(xiàng)3 = 枚舉值3,
... = ...
}
// 創(chuàng)建性別枚舉類
enum Gender {
Boy = 1,
Girl = 2,
Unknow = 3,
}
console.log("enum",Gender.Boy)//1
console.log("enum",Gender.Girl)//2
console.log("enum",Gender.Unknow)//3
// 使用性別枚舉
let userSex: Gender = Gender.Boy;
console.log("userSex",userSex)//1
使用默認(rèn)枚舉值
enum 枚舉名{
枚舉項(xiàng)1,
枚舉項(xiàng)2,
枚舉項(xiàng)3,
......
}
enum GunTypeTwo{
M416,// ==>0
Ak47,// ==>1
Goza,// ==>2
}
TypeScript 數(shù)據(jù)類型 | 任意類型(any)
概念:any 代表任意類型芥映,一般在獲取 DOM 時(shí)使用
let name: any; 顯示的 any奈偏,聲明變量指定類型 any坞嘀,name可以賦任意類型的值
name = "zhangsan";
name = 18;
name = true;
let people; 隱示申明類型 any,聲明變量不指定類型霎苗,TS解析器會(huì)自動(dòng)判斷變量類型為 any
people = "lisi";
people = 18;
people = true;
any 類型的缺點(diǎn):可以給任意類型的變量賦值姆吭,這樣會(huì)關(guān)閉其他變量的 TS 類型檢測(cè)榛做。
let name: any;
name = "zhangsan";
name = 18;
name = true; 這個(gè)時(shí)候 name 的值是 boolean 類型
let item: string; item變量的類型是 string 類型
item = name; item 按理說只能賦值 string 類型的值唁盏,但是 name 的值是 boolean 類型内狸,但是 name 能賦值成功給 item。
所以一般建議用 unknown 代替 any 使用厘擂,unknown 表示未知類型的值
TypeScript 數(shù)據(jù)類型 | unknown
概念:unknown 實(shí)際上就是一個(gè)類型安全的 any
特點(diǎn):
1昆淡、unknown 類型的變量,可以賦任何類型的值刽严。
2昂灵、unknown 類型的變量,不能直接賦值給其他變量舞萄。直接賦值會(huì)報(bào)錯(cuò)
1眨补、unknown 類型的變量,可以賦任何類型的值
let gun: unknown;
gun = "m416";
gun = 222;
gun = false;
如果 unknown 類型的變量想賦值給其他類型的變量有以下幾種方法:
let bbb: unknown;
bbb = "lisi";
bbb = 22;
let c: string;
第一種 先進(jìn)行類型檢查再賦值
if(typeof(bbb) === "string"){
c = bbb;
}
第二種 通過類型斷言的方式賦值
類型斷言的作用:類型斷言可以用來(lái)告訴解析器變量的實(shí)際類型
語(yǔ)法:
1倒脓、變量 as 類型
2撑螺、<類型> 變量
c = bbb as string;
c = <string> bbb;
我們?cè)诮邮湛蛻糨斎?或 第三方代碼庫(kù)時(shí),還不能確定會(huì)返回什么類型的值時(shí)崎弃,此時(shí)可以使用 any 類型甘晤。
示例:
let txtName: any = document.getElementById("txtN");
TypeScript 數(shù)據(jù)類型 | void
概念:void 代表 空,一般用在無(wú)返回值的函數(shù)饲做。(在 TS 中线婚,函數(shù)有返回值,需要指定返回值類型)
有返回值
function sayHi1(): string{
return "hi,你好呀………………";
}
let re1 = sayHi1();
無(wú)返回值
function sayHi2(): void{
console.log("hi,你好呀………………");
}
sayHi2();
TypeScript 數(shù)據(jù)類型 | never
概念:never 代表 沒有返回值盆均,常用于 作為拋出異常 或 無(wú)限循環(huán)的 函數(shù)返回類型
無(wú)限循環(huán)
function test(): never{
while(true){
}
}
拋出異常
function test2(): never{
throw new Error("拋出異常");
}
補(bǔ)充:never 類型是 ts 中的底部類型塞弊,所有類型都是 never 類型的 父類。所以 never 類型值 可以賦給任意類型的變量
let x: never = test();
let y: never = test();
TypeScript 類型注解 泪姨、 類型推斷
類型推斷概念:如果變量的聲明和初始化是在同一行,可以省略掉變量類型的聲明.
類型注解
let 變量名: 變量類型 = 值;
let num: number = 11
let name: string = "LBipanda"
類型推斷
let 變量名 = 值; 相當(dāng)于 let 變量名: 變量類型 = 值;
驗(yàn)證:
let age = 18;//此時(shí)變量 age 的類型推斷為 number
age = "jack";//報(bào)錯(cuò),因?yàn)樽兞?age 的類型是 number
TypeScript 數(shù)據(jù)類型 | 聯(lián)合類型
概念:如表示值可以取多種類型中的一種.
let 變量名: 變量類型1 | 變量類型2 = 值;
注意:
1.聯(lián)合類型的共有屬性是不會(huì)報(bào)錯(cuò);
2.在賦值的時(shí)候確認(rèn)類型;
//1.聯(lián)合類型的共有屬性是不會(huì)報(bào)錯(cuò);
people = "LBipanda"
console.log(people.length);
people = 18
console.log(people.length);//報(bào)錯(cuò)居砖,類型“number”上不存在屬性“l(fā)ength” 2.在賦值的時(shí)候確認(rèn)類型;
TypeScript 數(shù)據(jù)類型 | 交叉類型(&)
交叉類型是將多個(gè)類型合并為一個(gè)類型, 表示"并且"的關(guān)系,用&連接多個(gè)類型, 常用于對(duì)象合并:
interface A {a:number};
interface B {b:string};
const a:A = {a:1};
const b:B = {b:'1'};
const ab:A&B = {...a,...b};
3、TypeScript 函數(shù)
函數(shù)的定義
1驴娃、基本的函數(shù)定義
1奏候、函數(shù)聲明
function addd(x: number, y: number): number{
return x+y
}
2、函數(shù)表達(dá)式
let add: (x: number, y: number) => number = function(x, y) { //es5
return x+y;
};
let add1: (x: number, y: number) => number = (x, y) => { //es6
return x+y;
};
console.log(add(1,2))
console.log(add1(2,3))
2唇敞、使用接口定義函數(shù)
interface Add {
(x: number, y: number): number
}
let myFunc: Add = function(x, y){ //es5
return x+y;
};
let myFunc1: Add = (x, y) => { //es6
return x+y;
};
console.log(myFunc(3,6));
console.log(myFunc(6,4));
3,使用類型別名來(lái)定義函數(shù):
類型別名使用type關(guān)鍵字,相當(dāng)于為函數(shù)類型起一個(gè)名字
type Add = (x: number, y: number) => number
let add1: Add = function(x, y){ // es5
return x + y
}
let add2: Add = (x, y) => { // es6
return x + y
}
3.1蔗草、函數(shù) 返回值類型
function 函數(shù)名():返回值類型{//如果函數(shù)沒有返回值的話,則定義為 void
}
let 變量名:變量類型 = 函數(shù)名();//變量類型必須和函數(shù)的返回值一樣
function sayHi(): string{
return "hello world";
}
let res1: String = sayHi();
console.log(res1);
3.2疆柔、函數(shù) 形參 實(shí)參 類型
實(shí)參和 形參 的類型必須要一致
實(shí)參和 形參 的數(shù)量必須要一致
functio 函數(shù)名(形參1:類型, 形參2:類型):返回值類型{
}
let 變量名: 變量類型 = 函數(shù)名(實(shí)參1咒精, 實(shí)參2);
function person(name: string, age: number): void{
console.log(`你好旷档,我叫${name},我今年${age}歲了`)模叙;
}
person("Lbipanda",18);
小結(jié)
- 函數(shù)必須定義
,如果沒有返回值鞋屈,則定義返回值類型為
- 實(shí)參 和形參 的
要一致
- 實(shí)參 和形參 的
要一致
3.3范咨、函數(shù) 可選參數(shù)
function 函數(shù)名(形參 ?: 類型):返回值類型 {
}
調(diào)用:
可選參數(shù)可以傳實(shí)參也可以不傳
不傳遞實(shí)參 ==》 函數(shù)名();
傳遞實(shí)參 ==》 函數(shù)名(實(shí)參值);
function sayNo(name ?: string):void{
console.log(`${name || XXX},你在說什么`);
}
sayNo(); ===>XXX,你在說什么
sayNo("Lbipanda"); ===>Lbipanda,你在說什么
注意
3.4故觅、函數(shù) 默認(rèn)值
function 函數(shù)名(形參1:類型 = 默認(rèn)值1, 形參2: 類型 = 默認(rèn)值2): 返回值類型{
}
調(diào)用:
不傳實(shí)參 函數(shù)(); == 編譯后 ==》函數(shù)名(默認(rèn)值1, 默認(rèn)值2):
傳一個(gè)實(shí)參 函數(shù)(實(shí)參1); == 編譯后 ==》函數(shù)名(實(shí)參1, 默認(rèn)值2):
傳兩個(gè)實(shí)參 函數(shù)(實(shí)參1, 實(shí)參2); == 編譯后 ==》函數(shù)名(實(shí)參1, 實(shí)參2):
如果我想跳過第二個(gè)參數(shù),只傳第二個(gè)參數(shù)
函數(shù)(undefined, 實(shí)參 2); == 編譯后 ==》函數(shù)名(默認(rèn)值1, 實(shí)參2):
function timi(name: string = "緣妙不可言", count: number = 1): void{
console.log(`Timi渠啊,${name} 召喚師打了 ${count} 把游戲输吏。`);
}
timi(); ===》Timi,緣妙不可言 召喚師打了 1 把游戲替蛉。
timi("北港不夏"); ===》Timi贯溅,北港不夏 召喚師打了 1 把游戲。
timi("北港不夏",3); ===》Timi躲查,北港不夏 召喚師打了 3 把游戲它浅。
timi(undefined,5); ===》Timi,緣妙不可言 召喚師打了 5 把游戲镣煮。
3.5罚缕、函數(shù) 剩余參數(shù)
特點(diǎn):
1、剩余參數(shù) 只能 定義一個(gè)
2怎静、剩余參數(shù) 只能 定義為數(shù)組
3邮弹、剩余參數(shù) 只能 定義在形參列表最后
如果剩余參數(shù)不確定什么類型寫? ...形參: any[]
function 函數(shù)名(形參1: 類型, 形參2: 類型, ...形參3: 類型[]):返回值類型 {
}
function add(a: number, b: number,...restOfNum: number[]){
let ret = a + b;
for(let i of restOfNum){
ret += i;
}
console.log(ret)
}
add(1,2,3,4,5,6,7,8,9,10); ===》 55
3.5、函數(shù)重載
同名函數(shù)的參數(shù)的個(gè)數(shù)蚓聘、類型或者順序必須不同(其中有一個(gè)不一樣就滿足條件了) 叫函數(shù)的重載
重載允許一個(gè)函數(shù)接受不同數(shù)量或類型的參數(shù)時(shí)腌乡,作出不同的處理。 為同一個(gè)函數(shù)提供多個(gè)函數(shù)類型定義來(lái)進(jìn)行函數(shù)重載
在定義重載的時(shí)候夜牡,一定要把最精確的定義放在最前面与纽。因?yàn)椴檎抑剌d列表,會(huì)從第一個(gè)重載定義開始使用塘装,如果匹配成功的話就使用急迂,否則就繼續(xù)向下查下;最后函數(shù)實(shí)現(xiàn)時(shí),需要使用 |操作符或者?操作符蹦肴,把所有可能的輸入類型全部包含進(jìn)去(不確實(shí)的話可以寫any)
函數(shù)重載的意義在于能夠讓你知道傳入不同的類型參數(shù)得到不同的類型結(jié)果僚碎,如果傳入的參數(shù)不同锅知,但是得到的結(jié)果(類型)卻相同录择,那么這里就不需要使用函數(shù)重載
現(xiàn)在有這樣一個(gè)需求: 我們有一個(gè)add函數(shù),它可以接收string類型的參數(shù)進(jìn)行拼接盾似,也可以接收number類型的參數(shù)進(jìn)行相加
下面是按照之前我們所學(xué)知識(shí)寫的代碼
function add(arg1: string | number, arg2: string | number): number | string{
if (typeof arg1 === 'string' && typeof arg2 === 'string') {
return arg1 + arg2;
} else if (typeof arg1 === 'number' && typeof arg2 === 'number') {
return arg1 + arg2;
}
}
let a1 = add(1, 2);
let a2 = add('a', 'b');
上面的代碼在調(diào)用函數(shù)的時(shí)候矛双,定義的變量a1和a2沒有去定義類型渊抽,只是用了根據(jù)等號(hào)右邊的值去賦值給左邊的變量,事實(shí)上议忽,a1和a2也不能去指定為string或者number懒闷,因?yàn)閍dd函數(shù)的返回值就是一個(gè)聯(lián)合類型number | string,所以是實(shí)際工作中如果發(fā)生了這種事情,會(huì)導(dǎo)致a1和a2使用變得非撤吖溃混亂帮辟,接下來(lái)我們使用函數(shù)重載的形式對(duì)代碼進(jìn)行優(yōu)化
先進(jìn)行函數(shù)的重載,定義函數(shù)灵疮,將參數(shù)和返回值的類型定死
function add(arg1: string, arg2: string): string;
function add(arg1: number, arg2: number): number;
接下來(lái)進(jìn)行函數(shù)的實(shí)現(xiàn)
function add(arg1: string | number, arg2: string | number): number | string{
if (typeof arg1 === 'string' && typeof arg2 === 'string') {
return arg1 + arg2;
} else if (typeof arg1 === 'number' && typeof arg2 === 'number') {
return arg1 + arg2;
}
}
let a1 = add(1, 2);
let a2 = add('a', 'b');
這時(shí)候就可以明確a1和a2的類型了织阅,a1是number類型壳繁,a2是string類型
注意震捣,function add(arg1: string | number, arg2: string | number): number | string并不是重載列表的一部分,因此這里只有兩個(gè)重載:一個(gè)是接收數(shù)字闹炉,另一個(gè)接收字符串蒿赢。 以其它參數(shù)調(diào)用會(huì)產(chǎn)生錯(cuò)誤