TypeScript入门笔记(一)
TypeScript是微软开发的一个JavaScript的超集,个人感觉就是基于Js之上增加更多强类型约束与检查机制,是一个严格模式模式下的严格Js(禁止套娃)。特别是对于熟悉后台开发的同志,很多地方都会触发共鸣(特别是C#开发者,毕竟TypeScript是微软推出的,当然会有亲儿子的影子)。但是在学习TypeScript之前呢,最好要有JavaScript和ES6知识的基础,不然磕磕碰碰的学会打消积极性的。废话少说,开始水博客,这里记录本人学习ts路上的一些笔记,本人主要是根据官方文档和中文官网一篇篇看下来的,中途无意间撞见阮一峰大佬的教程觉得挺不错的,推荐想快速入门的同志们参考。
基本类型
1 console.log("TypeSrcipt 基本数据类型"); 2 /* 3 基本数据类型 4 */ 5 6 /* ---------------------------------------------------------------------- */ 7 //0. 布尔值 8 let isDone: boolean = false; 9 10 /* ---------------------------------------------------------------------- */ 11 //1. 数字类型 12 let age: number = 28; 13 //二进制表示法: 14 let binaryLiteral: number = 0b1010; 15 //八进制表示法: 16 let octalLiteral: number = 0o732; 17 18 /* ---------------------------------------------------------------------- */ 19 //2. 字符串 20 let fname: string = "Alice"; 21 // 模板字符串 22 let greet: string = `Hello ,my name is ${fname}, i am ${age} years old`; 23 console.log("string类型:", greet); 24 25 /* ---------------------------------------------------------------------- */ 26 //3. 数组类型 27 //使用「类型 + 方括号」来表示数组 28 let list1: number[] = [1, 2, 3, 4, 5]; 29 console.log("数组类型1 :", list1); 30 31 //使用数组泛型(Array Generic) Array<elemType> 来表示数组 32 let list2: Array<string> = ["Alice", "Bob", "John"]; 33 console.log("数组类型2 :", list2); 34 35 list1.push(6); //添加元素 36 list1.pop(); //弹出元素 37 console.log("按索引访问:list1[2]:", list1[2]) 38 39 //用 any 表示数组中允许出现任意类型 40 let list3: any[] = ['xcatliu', 25, { website: 'http://xcatliu.com' }]; 41 42 /* ---------------------------------------------------------------------- */ 43 //4. 元组类型 44 //类似C#中的Tuple类型 45 let card: [string, number]; 46 card = [fname, age]; 47 console.log("元组类型:", card); 48 console.log("元组可按索引访问 card[0]:", card[0]); 49 console.log("元组可按索引访问 card[1]:", card[1]); 50 /* 51 下面这个写法ts会报错,但是js可以通过并且正常运行 52 card[3] = 'world'; 53 console.log("元组类型:", card); 54 */ 55 56 //当添加越界的元素时,它的类型会被限制为元组中每个类型的联合类型: 57 let tom1: [string, number]; 58 tom1 = ['Tom', 25]; 59 tom1.push('male'); 60 //tom1.push(true); 61 console.log("元组类型2:", tom1); 62 63 /* ----------------------------------------------------------------------- */ 64 //5. 枚举类型 65 enum Gender { 66 Female = 0, 67 Male 68 } 69 let gender: Gender = Gender.Female; 70 console.log("枚举类型 gender:", gender); 71 console.log("gender === 0 :", gender === 0); //true 72 console.log(<number>Gender.Female + 1); //1 73 74 enum SeatLevel { 75 LevelI = "一等座", 76 LevelII = "二等座", 77 LevelIII = "站票" 78 } 79 let myTicket = SeatLevel.LevelIII; 80 console.log("myTicket === 站票 :", myTicket === "站票"); //true 81 //console.log("myTicket == 一等座 :", myTicket == "一等座"); //false 82 83 /* ----------------------------------------------------------------------- */ 84 //6. Any类型 85 //Any类型允许赋值为任意类型 86 let file: any = 123456789; 87 console.log(file); 88 file = "Quis labore excepteur aliqua aliquip." 89 console.log(file); 90 file = false; 91 console.log(file); 92 //在any类型上访问任何属性和任何方法都是允许的 93 //file.ifItExistProp; // okay, ifItExistProp might exist at runtime 94 //file.ifItExists(); // okay, ifItExists might exist at runtime 95 //file.toFixed(); // okay, toFixed exists (but the compiler doesn't check) 96 let repo: any[] = [1, "Nisi reprehenderit qui irure dolor sunt culpa occaecat.", false]; 97 console.log("any数组类型,repo[1]: ", repo[1]); 98 99 //联合类型:表示取值可以为多种类型中的一种 100 let numberOrString: string | number; 101 numberOrString = 'seven'; 102 console.log(numberOrString.length); // 5 103 104 numberOrString = 7; 105 //console.log(numberOrString.length); // 编译时报错:Property 'length' does not exist on type 'number' 106 107 /* ----------------------------------------------------------------------- */ 108 //7. void类型 109 function warnUser(): void { 110 console.log("This is my warning message"); 111 } 112 //声明一个void类型的变量没有什么大用,因为你只能为它赋予undefined和null 113 let unusable: void = undefined; 114 115 /* ----------------------------------------------------------------------- */ 116 /*8. nerver类型:表示的是那些永不存在的值的类型 117 never类型是那些总是会抛出异常或根本就不会有返回值的函数表达式的返回值类型 118 下面3个函数为常见的返回值类型为never的函数*/ 119 //(1)无法达到的终点的函数返回类型是 never 120 function infiniteLoop(): never { 121 while (true) { 122 } 123 } 124 //(2)抛出异常的函数也是一种无法到达“终点”的函数,所以返回类型也是 never 125 function error(message: string): never { 126 throw new Error(message); 127 } 128 //(3)智能推断的返回值类型为never 129 function fail() { 130 return error("Something failed"); 131 } 132 133 /* ----------------------------------------------------------------------- */ 134 /*9. object 类型 135 object表示非原始类型,也就是除number,string,boolean,symbol,null或undefined之外的类型。 136 */ 137 let person: object = { 138 fname: fname, 139 age: age, 140 gender: gender, 141 card: card 142 } 143 function Greet(p: object | null): void { 144 if (p == null) { 145 console.log("Hello everyone!"); 146 } 147 // let name = p.fname; 148 // let age = p.age; 149 // console.log(`Hello ,my name is ${name}, i am ${age} years old`); 150 }; 151 Greet(null); 152 Greet(person); 153 // Greet(fname); //报错 154 155 /* ----------------------------------------------------------------------- */ 156 /*10. 类型断言,类似与其他语言中的强制类型转换 */ 157 let someValue: any = "this is a string"; 158 //写法一: 159 let strLength: number = (<string>someValue).length; 160 console.log("strLength:", strLength); 161 //写法二:用as 162 strLength = (someValue as string).length; 163 console.log("strLength:", strLength);
TypeSrcipt 函数
1 /*------------------------------1.函数声明----------------------------------*/ 2 //1.1 为函数定义类型 3 function add(x: number, y: number): number { 4 return x + y; 5 } 6 let myAdd = function (x: number, y: number): number { 7 return x + y; 8 } 9 let myAddFunc = (x: number, y: number): number => x + y; 10 11 let [x, y] = [1, 2]; 12 console.log(`add : ${x} + ${y} = `, add(x, y)); 13 console.log(`myAdd: ${x} + ${y} = `, myAdd(x, y)); 14 console.log(`myAddFunc: ${x} + ${y} = `, myAddFunc(x, y)); 15 16 //1.2 书写完整函数类型 17 let myCompleteAddFunc: (baseValue: number, increment: number) => number 18 = function (x: number, y: number): number { 19 return x + y; 20 } 21 console.log(`myCompleteAddFunc: ${x} + ${y} = `, myCompleteAddFunc(x, y)); 22 /*--------------------------------------------------------------------------*/ 23 24 /*------------------------------2.可选参数-----------------------------------*/ 25 function buildName(firstName: string, lastName?: string) { 26 if (lastName) 27 return firstName + " " + lastName; 28 else 29 return firstName; 30 } 31 let result1 = buildName("Bob"); 32 let result2 = buildName("Bob", "Adams"); 33 /*--------------------------------------------------------------------------*/ 34 35 /*------------------------------3.默认参数-----------------------------------*/ 36 function buildName2(firstName: string, lastName = "Smith") { 37 return firstName + " " + lastName; 38 } 39 let result3 = buildName("Bob"); 40 let result4 = buildName("Bob", undefined); 41 let result5 = buildName("Bob", "Adams"); 42 /*--------------------------------------------------------------------------*/ 43 44 /*------------------------------4.剩余参数-----------------------------------*/ 45 function AddMany(...numbers: number[]) { 46 let sum = 0; 47 for (let index = 0; index < numbers.length; index++) { 48 sum += numbers[index]; 49 } 50 return sum; 51 } 52 let [w, z] = [3, 4]; 53 console.log(`AddMany ${x}+${y}+${w}+${z} = `, AddMany(x, y, z, w)); 54 /*--------------------------------------------------------------------------*/ 55 56 /*------------------------------5.箭头函数-----------------------------------*/ 57 // 注意:箭头函数能保存函数创建时的 this值,而不是调用时的值 58 let deck = { 59 suits: ["hearts", "spades", "clubs", "diamonds"], //[红,黑,草,方] 60 cards: Array(52), // 不带大小王的哦 61 createCardPicker: function () { 62 // 在使用箭头函数后,下面的这个this指代的就是deck这个对象了 63 return () => { 64 let pickedCard = Math.floor(Math.random() * 52); 65 let pickedSuit = Math.floor(pickedCard / 13); 66 67 return { suit: this.suits[pickedSuit], card: pickedCard % 13 }; 68 } 69 } 70 } 71 let cardPicker = deck.createCardPicker(); 72 let pickedCard = cardPicker(); 73 console.log("你拿到的牌是: " + pickedCard.card + " of " + pickedCard.suit); 74 /*--------------------------------------------------------------------------*/ 75 76 /*------------------------------6.函数重载----------------------------------*/ 77 let suits = ["hearts", "spades", "clubs", "diamonds"]; 78 //重载的话先把可能遇到的参数类型先一一列举出,再用最后一个使用any参数的函数囊括各个情况,具体实现每种参数情况下的处理方式 79 function pickCard(x: { suit: string; card: number; }[]): number; 80 function pickCard(x: number): { suit: string; card: number; }; 81 function pickCard(x: any): any { 82 // 如果传入的是一个对象或者数组,也就是用户传进来的就是几张牌,这样的话我们就从中抽一张 83 if (typeof x == "object") { 84 let pickedCard = Math.floor(Math.random() * x.length); 85 return pickedCard; 86 } 87 // 传入的是一个数组的话,就根据这个数抽一张牌 88 else if (typeof x == "number") { 89 let pickedSuit = Math.floor(x / 13); 90 return { suit: suits[pickedSuit], card: x % 13 }; 91 } 92 } 93 let myDeck = [{ suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }]; 94 let pickedCard1 = myDeck[pickCard(myDeck)]; 95 console.log("你拿到的牌是: " + pickedCard1.card + " of " + pickedCard1.suit); 96 97 let pickedCard2 = pickCard(18); 98 console.log("你拿到的牌是: " + pickedCard2.card + " of " + pickedCard2.suit); 99 /*--------------------------------------------------------------------------*/
TypeSrcipt 类
1 console.log("------------------------------------------------"); 2 console.log("TypeSrcipt 类"); 3 4 /*传统js中没有class的概念,从ES6引入*/ 5 /*---------------------------------1.类------------------------------------*/ 6 //1.1 定义一个类 7 //tips: 在ts中,类中变量和方法的默认访问修饰符是public 8 class Person { 9 //局部变量 10 protected readonly name: string; 11 protected readonly age: number; 12 private phone: string = "138555555555"; 13 private address: string = "221B Baker St"; 14 15 //构造函数 16 constructor(name: string, age: number) { 17 this.name = name; 18 this.age = age; 19 } 20 /* 上面的简化写法:在一个地方定义并初始化一个成员 21 constructor(readonly name: string,readonly age: number) { 22 } 23 */ 24 25 //存取器(属性) 26 get contact(): string { 27 return `${this.phone}—${this.address}`; 28 } 29 set contact(newVal: string) { 30 if (newVal && newVal.includes("—")) { 31 [this.phone, this.address] = newVal.split("—"); 32 } 33 else { 34 console.log("Incorrect format"); 35 } 36 } 37 //方法 38 greet() { 39 console.log(`Hi, i am ${this.name}`); 40 } 41 } 42 //1.2 创建一个类的实体 43 let sherlock = new Person("sherlock", 24); 44 sherlock.greet(); //Hi, i am sherlock 45 //读属性 46 console.log(sherlock.contact); //138555555555—221B Baker St 47 //写属性 48 sherlock.contact = "13966666666—211B Baker St" 49 //再读新属性 50 console.log(sherlock.contact); //13966666666—211B Baker St 51 /*--------------------------------------------------------------------------*/ 52 53 /*---------------------------------2.继承------------------------------------*/ 54 //2.1 继承类的关键字:extends 55 class Doctor extends Person { 56 diagnose() { 57 console.log(`diagnose illness...`) 58 } 59 } 60 61 //如果子类也有自己的构造函数,那么还必须要调用父类的构造函数,写法就是super() 62 class Teacher extends Person { 63 private school: string; 64 constructor(name: string, age: number, school: string) { 65 super(name, age); 66 this.school = school; 67 } 68 teach() { 69 console.log(`teach at ${this.school} ...`); 70 } 71 } 72 73 //2.2 创建子类 74 let Alice = new Doctor("Alice", 28); 75 Alice.greet(); //Hi, i am Alice 76 Alice.diagnose(); //diagnose illness... 77 78 let Howard: Teacher = new Teacher("Howard", 35, "Kw HighSchool"); 79 Howard.greet(); //Hi, i am Howard 80 Howard.teach(); //teach at Kw HighSchool ... 81 /*--------------------------------------------------------------------------*/ 82 83 /*-------------------------------3.抽象类------------------------------------*/ 84 //给其他类来继承的,不能创建一个抽象类的实例 85 abstract class Animal { 86 abstract makeSound(): void; //抽象类的抽象方法我们不需要实现,关键字:abstract 87 88 move(): void { 89 console.log('roaming the earch...'); 90 } 91 } 92 //定义抽象类的派生类 93 class Dog extends Animal { 94 makeSound(): void { 95 console.log('wong wong wong...'); 96 } 97 98 eat(): void { 99 console.log('happiness...') 100 } 101 } 102 103 let xiaobai: Animal; // 允许创建一个对抽象类型的引用 104 xiaobai = new Dog(); // 允许对一个抽象子类进行实例化和赋值 105 xiaobai.makeSound(); // wong wong wong... 106 //xiaobai.eat(); // Error :因为声明的是Animal类型,Dog类的方法无法调用到
TypeSrcipt 接口
1 console.log("------------------------------------------------"); 2 console.log("TypeSrcipt 接口"); 3 //接口作用的简单总结:定义契约 4 5 /*-------------------------------1.接口的作用----------------------------------*/ 6 //TypeScript中接口与C#中有一点不一样,TypeScript中的接口是一个非常灵活的概念,除了可用于对类的一部分行为进行抽象以外,也常用于对「对象的形状(Shape)」进行描述。 7 interface LabelledValue { 8 label: string; 9 } 10 11 //用接口进行“约束”的对象,其字段不能多一个也不能少一个 12 let obj: LabelledValue = { 13 label: 'myObj', 14 //NO: 1002 //报错 15 } 16 17 function printLabel(labelledObj: LabelledValue) { 18 console.log(labelledObj.label); 19 } 20 21 let myObj = { size: 10, label: "Size 10 Object" }; 22 printLabel(myObj); 23 /*---------------------------------------------------------------------------*/ 24 25 /*-------------------------------2.可选参数------------------------------------*/ 26 interface SquareConfig { 27 color?: string; //加上 ? 就表示参数是可选的了 28 width?: number; 29 } 30 31 let squareValue: SquareConfig = { 32 width: 10 33 //width2: 20 //但是新属性还是不行的 34 } 35 36 function createSquare(config: SquareConfig): { color: string; area: number } { 37 let newSquare = { color: "white", area: 100 }; 38 if (config.color) { 39 newSquare.color = config.color; 40 } 41 if (config.width) { 42 newSquare.area = config.width * config.width; 43 } 44 return newSquare; 45 } 46 47 let mySquare = createSquare({ color: "black" }); 48 /*---------------------------------------------------------------------------*/ 49 50 /*-------------------------------3.任意属性------------------------------------*/ 51 //接口允许有一个任意的属性 52 //需要注意的是:一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集 53 interface Dop { 54 name: string; 55 age?: number; 56 [prop: string]: any; //我们定义的任意类型是any类型,name和age的类型都是any的子集,所以编译通过,当然这里也可以使用联合类型来定义“stirng | number” 57 } 58 let tom: Dop = { 59 name: 'Tom', 60 gender: 'male' 61 }; 62 let jerry: Dop = { 63 name: 'Tom', 64 age: 25, 65 gender: 'male' 66 }; 67 /*---------------------------------------------------------------------------*/ 68 69 /*----------------------------4.函数类型的接口---------------------------------*/ 70 /* 刚刚上面使用接口去约束了参数的形式,接口也可以约束函数的形式 71 */ 72 73 interface SearchFunc { 74 (source: string, subString: string): boolean; 75 } 76 77 /* 78 ① 参数名称不是强制一样的,只要参数类型相同即可 79 ② 实现接口的方法,如果不指定参数类型,TypeScript的类型系统会推断出参数类型 80 */ 81 let mySearch: SearchFunc; 82 mySearch = function (src, sub) { 83 let result = src.search(sub); 84 return result > -1; 85 } 86 /*---------------------------------------------------------------------------*/ 87 88 /*----------------------------5.可索引类型接口----------------------------------*/ 89 interface IArray { 90 [index: number]: string 91 } 92 //这种方式也可以来定义一个数组,但是单纯定义一个数组时我们不会这么定义,太复杂了 93 var myArr: IArray = ["jack", "john", "jim"]; 94 95 interface IObj { 96 [index: string]: string 97 } 98 99 var myObject: IObj = { name: "jack", email: "123@126.com" }; 100 /*----------------------------------------------------------------------------*/ 101 102 /*-------------------------------6.类类型接口----------------------------------*/ 103 //定义一个接口来约束一个英雄该有的内涵,嘿嘿 104 interface IHero { 105 position: heroType; 106 level: number; 107 heroName: string; 108 phrase: string; 109 attack(): void; 110 } 111 enum heroType { 112 warrior, 113 wizard, 114 archer, 115 tank, 116 assassin 117 } 118 //定义类型实现接口IHero,关键字“implements” 119 class Hero implements IHero { 120 position: heroType; 121 level: number; 122 heroName: string; 123 phrase: string; 124 constructor(pos: heroType, lev: number, name: string, phrase: string) { 125 this.position = pos; 126 this.level = lev; 127 this.heroName = name; 128 this.phrase = phrase; 129 } 130 attack(): void { 131 console.log(`${this.phrase}!!!`); 132 } 133 } 134 let yasuo: Hero = new Hero(heroType.warrior, 1, "疾风剑豪", "ha sa ki"); 135 yasuo.attack(); 136 /*---------------------------------------------------------------------------*/