• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

深入浅出 Typescript 学习笔记

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

TypeScript 是 JavaScript 的一个超集,支持 ECMAScript 6 标准。

TypeScript 由微软开发的自由和开源的编程语言。

TypeScript 设计目标是开发大型应用,它可以编译成纯 JavaScript,编译出来的 JavaScript 可以运行在任何浏览器上。

以上为网上对 Typescript 的一些解释,那我们为什么要学 Typescript?

提到前端我们首先会想到 HTML,CSS,JavaScript 三大家族,我们掌握这三个就可以在前端界获得一席之地,怎么突然又冒出个 Typescript,真心是学不动了,但是众所周知,Vue 创始人尤雨溪尤大大已经宣布 Vue3.x 代码库将使用 Typescript 编写,并且在知乎上对于"Typescript 不适合在 Vue 开发业务中使用吗?" 的提问中做出回答,传送门:https://www.zhihu.com/question/310485097/answer/591869966,Vue 又是现在国内主流的前端框架之一,只能说,如果不学 Typescript,尤大大都救不了你了。

众所周知,从本质上来说,JavaScript是一种自由松散语言,它的语法规则并不是那么严格。正因为如此,我们就更容易犯错,而且,即使是在运行的时候,我们也不能找到所有的错误。鉴于此,TypeScript作为JavaScript的增强版,它的语法更严格,我们在编写代码的时候就能够发现大部分错误。不仅如此,按照TypeScript官方的说法,TypeScript使得我们能够以JavaScript的方式实现自己的构思。TypeScript对面向对象的支持也非常完善,它拥有面向对象编程语言的所有特性。

TypeScript最大的目的是让程序员更具创造性,提高生产力,它将极大增强JavaScript编写应用的开发和调试环节,让JavaScript能够方便用于编写大型应用和进行多人协作。

不过目前最后运行时还需要将TypeScript编译为JavaScript。

那接下来我们就来看看如何安装使用 Typescript。

在安装 Typescript 之前我们要先安装 NodeJs,然后运行

npm install -g typescript

以上命令会在全局环境下安装 tsc 命令,安装完成之后,我们就可以在任何地方执行 tsc 命令了。

编译一个 TypeScript 文件很简单:

tsc demo.ts

运行上面的代码,我们就可以将 demo.ts 生成一个可以让浏览器解析的 demo.js 的文件。

我们约定使用 TypeScript 编写的文件以 .ts 为后缀,用 TypeScript 编写 React 时,以 .tsx 为后缀。

那么我们在编写代码的时候不能每次都手动编译 .ts 文件,我们想要的是实时编译 .ts 文件,接下来我们就以 webstorm 编辑器来使 .ts 文件进行实时编译。其他编辑器可自行百度如何实时编译。

webstorm 版本:

创建一个 demo 项目,然后在项目中创建一个 tsconfig.json 的文件,内容如下:

这里只是简单的配置,详细参数配置:https://www.tslang.cn/docs/handbook/tsconfig-json.html

 

打开Webstorm,为TypeScript文件更改编译设置,File->Settings->Tool->File Watchers->TypeScript,这里我们需要选择TypeScript,但是File Watchers下默认是不存在的。需要点击右侧“+”号,选择,弹出 New Watcher,设置好圈红线的部分,点击ok。勾选“TypeScript”,点击ok。

 

 

 

File->Settings->Languages & Frameworks->TypeScript

 

 

 根据上面的操作我们就可以实时编译 .ts 文件了。

目录结构如下,在 index.html 中银润 test.js

test.ts 会实时编译为 test.js 文件。

test.ts

 
test.js 

 

index.html 开发者工具中的打印日志

 根据上面的步骤我们就可以对 ts 文件进行实时编译了,接下来我们就来看一下 Typescript 的一些基本用法。

 从上图我们可以看出 Typescript 包含了 ES6 和 ES5,那我们就可以在 typescript 中使用 es5 和 es6,同时进行了扩展,语法上跟我们之前讲的 Java 语法有很多相似。

 

Typescript 基础类型

Typescript 基础类型有:布尔类型(boolean)、数字类型(number)、字符串类型(string)、数组类型(array)、元组类型(tuple)、枚举类型(enum)、任意类型(any)、null 和 undefined 、void、never 类型等,接下来我们就一一来看一下这些类型的应用。

 1 /**
 2  * 在定义完参数进行赋值时,
 3  * 必须按照给定的参数类型进行赋值
 4  * 否则会出现编译问题
 5  * 但在页面当中还是会进行编译
 6  * 但是不提倡这么做
 7  */
 8 // boolean
 9 let flag: boolean = true;
10 console.log(flag); // true
11 // let flag1:boolean = 123; // Type '123' is not assignable to type 'boolean'.
12 
13 // number
14 let num: number = 123;
15 console.log(num); // 123
16 
17 // string
18 let str: string = "abc";
19 console.log(str); // abc
20 
21 // array 两种定义方式
22 let arrS: string[] = ["123", "abc"]; // 数组内元素必须为 string
23 let arrA: Array<number> = [123, 456]; // 数组内元素必须为 number
24 console.log(arrS); // ["123", "abc"]
25 console.log(arrA); // [123, 456]
26 
27 // tuple 元祖类型,属于数组的一种,可以为每个元素指定类型
28 let tup: [number, string] = [123, "abc"];
29 console.log(tup); // [123, "abc"]
30 // let tup1:[number,string] = ["abc",123];  // 报错
31 
32 // enum 枚举类型
33 /**
34  * 在日常生活或者开发中
35  * 很多都不能或者不容易使用数据表达
36  * 如:颜色,日期,角色,性别等
37  * 例如在开发中我们常用 -1 表示 error,用 0 表示 success
38  * 这个就可以成为枚举
39  */
40 enum Flag {
41     error = -1,
42     success = 0
43 }
44 
45 let e: Flag = Flag.error;
46 console.log(e); // -1
47 
48 /**
49  * 如果枚举元素不赋值,则默认取值为下标
50  * 如果某个元素取值为数字 n
51  * 后面的元素如果不取值则默认为 n+1,以此类推
52  * 如果某个元素取值为 string 类型
53  * 后面的元素则必须取值,取值类型无要求
54  */
55 enum Color {
56     red, blue, black = 4, yellow, green = "green", white = 123
57 }
58 
59 let red: Color = Color.red;
60 let blue: Color = Color.blue;
61 let black: Color = Color.black;
62 let yellow: Color = Color.yellow;
63 let green: Color = Color.green;
64 let white: Color = Color.white;
65 console.log(red, blue, black, yellow, green, white); // 0 1 4 5 "green" 123
66 
67 // undefined
68 let un: undefined;
69 console.log(un); // undefined
70 
71 // 我们也可以通过 | 来赋值多种类元素
72 let uns: number | undefined;
73 
74 // any 类型,可以为任意类型
75 let an: any = 123;
76 console.log(an); // 13
77 an = "abc";
78 console.log(an) // abc

在上面的代码中,我们演示了一下 Typescript 中的一些基本类型的使用,接下来我们再来看一下在函数中数据类型的应用。

Typescript 函数方法

 1 // 如果没有返回值,则在方法名后面加 :void
 2 function test(): void {
 3     console.log("test")
 4 }
 5 
 6 test(); // test
 7 
 8 // 如果有返回值,则在方法名后面加 :返回值的类型
 9 function num(): number {
10     return 123;
11 }
12 
13 console.log(num()); // 123
14 
15 function str(): string {
16     return "abc";
17 }
18 
19 console.log(str()); // "abc"
20 
21 // 定义传参
22 function getData(name: string, age: number): void {
23     console.log(`${name}--${age}`)
24 }
25 
26 getData("张三", 18); // 张三--18
27 // getData("张三"); // 报错 Expected 2 arguments, but got 1.
28 // getData("张三","18"); // 报错 Argument of type '"18"' is not assignable to parameter of type 'number'.
29 
30 /**
31  * 方法可选参数
32  * 在参数后面添加 ?
33  * 表示该参数为可选参数
34  */
35 function getInfo(name: string, age?: number): string {
36     if (age) {
37         return `${name}--${age}`
38     } else {
39         return `${name}`
40     }
41 }
42 
43 console.log(getInfo("张三", 18)); // 张三--18
44 console.log(getInfo("张三")); // 张三
45 
46 /**
47  * 方法默认参数
48  * 在参数后面直接赋值
49  * 表示该参数直接当做了被传入参数
50  */
51 function getUser(name: string, age: number = 18): string {
52     if (age) {
53         return `${name}--${age}`
54     } else {
55         return `${name}`
56     }
57 }
58 
59 console.log(getUser("张三", 18)); // 张三--18
60 console.log(getUser("张三")); // 张三--18
61 
62 /**
63  * 剩余参数
64  * 如果在传参过程中
65  * 前面的参数已经给定
66  * 在调用函数传参时会先将
67  * 传入的参数作为指定参数
68  * 剩余参数必须为最后一个参数传入
69  */
70 // 正常的传参
71 function sum1(...arr: number[]): number {
72     let sum: number = 0;
73     for (let i = 0; i < arr.length; i++) {
74         sum += arr[i];
75     }
76     return sum;
77 }
78 console.log(sum1(1, 2, 3, 4)); // 10
79 
80 // a 作为第一个参数,其余的为剩余参数,即 (a,剩余参数)
81 function sum2(a: number, ...arr: number[]): number {
82     let sum: number = 0;
83     for (let i = 0; i < arr.length; i++) {
84         sum += arr[i];
85     }
86     return sum;
87 }
88 console.log(sum2(1, 2, 3, 4)); // 10

 在上面的代码中,我们实现了在 ts 中如何定义方法和如何进行方法传参,跟定义基本类型一样需要对方法进行有效的规定。

接下来我们再来看一下在 ts 中如何实现类和类的继承。

Typescript 类

在 ES5 中,我们是通过构造方法和原型链的方式进行继承的,在之前的文章中我们也讲过如何实现继承,传送门:https://www.cnblogs.com/weijiutao/p/12090916.html,Typescript 包含 ES6,所以本章着重讲解一下 ES6 中 class 关键字的类和继承。

 1 // 在 ts 中定义类
 2 class Person {
 3     name: string;
 4 
 5     constructor(name: string) {
 6         this.name = name;
 7     }
 8 
 9     getName(): void {
10         console.log(this.name);
11     }
12 
13     setName(name: string): string {
14         return this.name = name;
15     }
16 
17     work(): void {
18         console.log("父类在工作")
19     }
20 }
21 
22 let p = new Person("张三");
23 p.getName(); // 张三
24 p.setName("李四");
25 p.getName(); // 李四
26 p.work(); // 父类在工作
27 
28 // 在 ts 中实现继承
29 /**
30  * 通过 extends 继承了 Person 的属性和方法
31  */
32 class Student extends Person {
33     constructor(name: string) {
34         super(name);
35     }
36 
37     // 子类自己的方法
38     run(): void {
39         console.log(this.name + "在运动")
40     }
41 
42     // 子类重写父类的方法
43     work(): void {
44         console.log("子类在工作")
45     }
46 
47 }
48 
49 let s = new Student("王五");
50 s.getName(); // 王五
51 s.run(); // 王五在运动
52 s.work(); // 子类在工作
* 类里面的修饰符
* Typescript 里面定义属性的时候
* 给我们提供了三种修饰符
* public:公有类型,在类里面、子类、类外面都可以访问
* protected:保护类型,在类里面,子类里面可以访问,类外面无法访问
* private:私有类型,在类里面可以访问,子类,类外面无法访问
* 属性不加修饰符,默认为公有属性
 1 /**
 2  * 类里面的修饰符
 3  * Typescript 里面定义属性的时候
 4  * 给我们提供了三种修饰符
 5  * public:公有类型,在类里面、子类、类外面都可以访问
 6  * protected:保护类型,在类里面,子类里面可以访问,类外面无法访问
 7  * private:私有类型,在类里面可以访问,子类,类外面无法访问
 8  * 属性不加修饰符,默认为公有属性
 9  */
10 
11 class Person {
12     name: string;
13     public age: number = 18;
14     protected sex: string = "男";
15     private city: string = "北京";
16 
17     constructor(name: string) {
18         this.name = name;
19     }
20 
21     // 在本类中访问 public 类型
22     getName(): void {
23         console.log(this.name);
24     }
25 
26     // 在本类中访问 public 类型
27     getAge(): void {
28         console.log(this.age);
29     }
30 
31     // 在本类中访问 protected 类型
32     getSex(): void {
33         console.log(this.sex);
34     }
35 
36     // 在本类中访问 private 类型
37     getCity(): void {
38         console.log(this.city);
39     }
40 
41 }
42 
43 let p = new Person("张三");
44 // 外部访问 public 类型
45 console.log(p.name); // 张三
46 // 外部访问 public 类型
47 console.log(p.age); // 18
48 // 外部访问 protected 类型
49 // console.log(p.sex); // 报错 Property 'sex' is protected and only accessible within class 'Person' and its subclasses.
50 // 外部访问 private 类型
51 // console.log(p.city); // 报错 Property 'city' is private and only accessible within class 'Person'.
52 
53 class Student extends Person {
54     constructor(name: string) {
55         super(name);
56     }
57 
58     getInfo(): void {
59         // 在子类中访问 public 属性
60         console.log(this.name);
61         // 在子类中访问 private 属性
62         console.log(this.age);
63         // 在子类中访问 protected 属性
64         console.log(this.sex);
65         // 在子类中访问 private 属性
66         // console.log(this.city) // 报错 Property 'city' is private and only accessible within class 'Person'.
67     }
68 }
69 
70 let s = new Student("王五");
71 s.getInfo(); // 王五 18 男

在上面的代码中我们实现了一下 class 中的修饰符,接下来我们再来看一下 class 的静态属性、静态方法

 1 /**
 2  * 通过 static 关键字可以定义静态属性和静态方法
 3  * 静态属性和静态方法直接通过 类. 来实现
 4  */
 5 
 6 class Person {
 7     name: string;
 8     static age: number = 18;
 9 
10     constructor(name: string) {
11         this.name = name;
12     }
13 
14     run(): void {
15         console.log(`${this.name}在运动`)
16     }
17 
18     /**
19      * 静态方法无法通过 this 调用类里面的属性
20      * 通过 类. 调用
21      */
22     static work(): void {
23         console.log("父类静态方法" + Person.age)
24     }
25 }
26 
27 let p = new Person("张三");
28 p.run(); // 张三在运动
29 console.log(p.name); // 张三
30 
31 console.log(Person.age); // 18
32 Person.work(); // 父类静态方法18

在上面的代码中我们实现了一下 class 中的静态属性、静态方法,接下来我们再来看一下 class 的多态

 1 /**
 2  * 我们在定义类方法后
 3  * 子类继承该类,并根据实际情况
 4  * 来实现自己所需要的类方法
 5  */
 6 class Person {
 7     name: string;
 8     age: number;
 9 
10     constructor(name: string) {
11         this.name = name;
12     }
13 
14     work(): void {
15         console.log(`${this.name}在工作`)
16     }
17 
18 
19 }
20 
21 class Student extends Person {
22     constructor(name: string) {
23         super(name);
24     }
25 
26     run(): void {
27         console.log(`${this.name}在学习`)
28     }
29 }
30 let s = new Student("张三");
31 s.run(); // 张三在学习
32 
33 class Teacher extends Person {
34     constructor(name: string) {
35         super(name);
36     }
37 
38     run(): void {
39         console.log(`${this.name}在讲课`)
40     }
41 }
42 let t = new Teacher("李四");
43 t.run(); // 李四在讲课

在上面的代码中,我们定义了 Person 类并定义了一个 work 方法,然后 Student 和 Teacher 类分别继承了 Person,但是根据自己的角色重写了 work 方法,这就是一种多态。

接下来我们再来看一下 class 中的抽象类

 1 /**
 2  * 抽象类是提供其他类继承的基类,不能被实例化
 3  * abstract 关键字定义抽象类和抽象方法
 4  * 子抽象类中的抽象方法不能包含具体实现,必须在实现类中实现
 5  * 抽象类和抽象方法只是用来定义标准
 6  */
 7 abstract class Person {
 8     name: string;
 9 
10     constructor(name: string) {
11         this.name = name;
12     }
13 
14     abstract work(): any;
15 }
16 
17 // 无法被实例化
18 // let p = new Person(); // 报错 error TS2511: Cannot create an instance of an abstract class.
19 
20 class Student extends Person {
21     constructor(name: string) {
22         super(name);
23     }
24 
25     work(): any {
26         console.log(`${this.name}在学习`)
27     }
28 }
29 
30 let s = new Student("张三");
31 s.work(); // 张三在学习

 

Typescript 接口

在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面,几口是一种限制和规范的作用。接口定义了某一批类所需要遵循的规范,接口不关心这些类的内部状态数据,也不关心这些类里面方法的实现细节,它只规定这批类里面必须提供某些方法,提供这些方法的类就可以满足实际需要,Typescript 中的接口类似于 Java,同时还增加了更灵活的接口类型,包括属性、函数、数组类等。

 在日常生活中,我们会接触到很多类似接口的问题,比如 USB 接口,我们在电脑上插鼠标,键盘,U盘的时候不用去考虑它到底能不能插进去,只要型号对了就肯定能插进去,接口就相当于一个标准,你要想把鼠标插到我的电脑上,在出厂时就必须遵守该电脑定义的接口标准。

接下来我们就来看一下接口:

1、属性和类接口

 1 interface FullName {
 2     firstName:string,
 3     lastName:string,
 4     sayHi: ()=>string
 5 }
 6 
 7 let person:FullName = {
 8     firstName:"张",
 9     lastName:"三",
10     sayHi: ():string =>{return "hell world"}
11 };
12 
13 console.log(person.firstName); //
14 console.log(person.lastName); //
15 console.log(person.sayHi()); // hello world

在上面的代码中,我们通过 interface 编写了一个 FullName 的接口,然后定义了一个 person 的变量来实现这个接口,那么我们就可以使用该接口里面的属性了。

 2、函数类型接口

 1 // 对方法传入的参数以及返回值进行约束
 2 interface encrypted {
 3     (key: string, value: string): string
 4 }
 5 
 6 // key 和 value 必须符合 encrypted 接口的 string 类型约束
 7 let getData: encrypted = (key: string, value: string) => {
 
                       
                    
                    

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
typescript中的esModuleInterop选项发布时间:2022-07-18
下一篇:
TypeScript 源码详细解读(1)总览发布时间:2022-07-18
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap