TypeScript 学习
小知识,大挑战!本文正在参与「程序员必备小知识」创作活动
本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。
TypeScript 导言
TS 是什么及其优点
Typescript 是一种由微软开发的自由开源的编程语言,它是 js 的一个超集,扩展了 js 的语法,主要提供了类型系统和对 ES6 的支持。Angular2 与 Vue3 即是 TS 开发的。
其优势为强大的 IDE 支持:
1. 类型检查:在 TS 中允许为变量自定义类型
2. 语法提示
3. 重构
使用 TS 的优点:
1.类型检测:在 Typescript 中为变量指定具体类型时,IDE会做出类型检测,这个特性减少在开发阶段犯错几率。
2.语法提示:在IDE里编写 Typescript 代码时,IDE 会根据你当前的上下文,把你能用的类、变量、方法和关键字都给你提示出来。直接选择,这个特性提高开发效率。
3.便于重构:重构是说你可以很方便的去修改你的变量或者方法的名字或者是文件的名字,当你做出这些修改的时候,IDE 会帮你自动引用这个变量或者调用这个方法地方的代码自动帮你修改掉。
4.活跃社区: Typescript 拥抱 es6 的规范,也支持部分 ESNext 草案规范,大部分的第三方库提供 Typescript 类型定义的文件。
TypeScript 的最大特点是静态类型,不同于 javascript 的动态类型,静态类型有以下优势∶
其一,静态类型检查可以做到 early fail ,即你编写的代码即使没有被执行到,一旦你编写代码时发生类型不匹配,语言在编译阶段(解释执行也一样,可以在运行前)即可发现。
其二,静态类型对阅读代码是友好的,针对大型应用,方法众多,调用关系复杂,不可能每个函数都有人编写细致的文档,所以静态类型就是非常重要的提示和约束。此外 TS 还实现了类,接口,枚举,泛型,方法重载等语法糖,方便了前端开发。
学习 Ts 的前提
学习 Ts 需要理解接口(interfaces)、泛型(Generics)、类(classes)、枚举类型(Enums)等前端开发不熟的知识点。
接口(Interfaces):可以用于对[对象的形状(Shape)]进行描述
泛型(Generics):是指在定义函数、接口或类的事或,不预先指定具体的类型,
而在使用的时候再指定类型的一种特性
类(Class):定义了一件事物的抽象特点
一、 TypeScript 简单了解
1、 Ts 环境安装
全局安装好 Ts 准备开始学习。因为其浏览器本身并不能解析 ts,所以需要在编写好 ts 时,需要使用命令将 ts 编译为 js 文件。
安装:
npm i -g typescript
查看版本
tsc -v
编译 ts 文件
tsc index.ts
2、 Ts 简单使用
刚了解到 ts 时,给我的感觉就是 ts 让 js 变得和 java 一样成为了“强类型”语言,因为其在声明变量时就得规定其定义的数据类型。
例:
定义一个 类型为 number,值为 15 的变量 num
// num(变量名) :number(变量类型) = 15(具体值) let num:number = 15复制代码
定义一个 类型为 string,值为 'abc' 的变量 str
// str(变量名) :string(变量类型) = 'abc'(具体值) let str:string = 'abc'复制代码
这里再看一个示例:
因为以前的 js 并没有强规定传的参数类型,所以在调用函数时,所传的参数并没有限制,也就导致了我们在团队开发时调用别人的函数时,可能会因其不熟悉其函数,而传错了参数导致的意外 Bug。
而且 js 的函数在调用时并不会报错,而是会在运行后抛出错误,这可能就导致了我们代码出 Bug 时我们却不知道 Bug在哪的问题。
但是 ts 则不同,ts 在传参的同时便会检索传入函数的参数内容是否符合规范,如若不符合便会直接报错。
// 计算两个参数的和 function sum(){ return x + y } // 调用时并不会报错,但是在运行后会报错 sum(true, 3) // ts 中可以提前定义传进来的参数必须是 number,可以有效防止使用时传其他类型的数据进来 function sum(x: number, y: number){ return x + y } // 正确,不会报错 sum(1, 2) // 报错 sum(true, 3)复制代码
二、 Ts 中定义变量、数组、对象
1. ts 中定义变量
指定类型的方式有三种:单类型定义、联合定义、任意类型定义
// 单类型定义 var id: number = 1 // 正确,不报错 id = 2 // 报错,类型定义错误 id = true // 联合类型定义 // 定义这个 id 可以是字符串也可以是 number var id: string | number // 类型不符合,报错 id = true // 任意类型定义,表示可以定义任何类型的数据 var s: any // 这样就和 js 中定义变量是一致的,什么类型都可以定义并改变 // 不报错 s = true复制代码
主要知识点:
单类型定义:
var id: number = 1
联合类型定义:var name:
number | string = '你好'
任意类型定义:
var age: any = '18'
2. ts 定义数组
ts 中定义数组的方式有两种,一种较为简单,类似于变量,但数组不能使用联合类型。
// 1. 简单方式: // 定义数组只能添加 number 类型 let arr: number[] = [1, 2, 3] // 不能使用联合类型定义 let arr1: string | number = [1, 2, '3'] // 报错 // 使用 any 任意类型 let arr2: any[] = [1, 2, '3'] // 2. 泛型(Generics)定义: // 泛型(Generics):是指在定义函数、接口或类的数据时,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。 // <T>: T 表示变量,可以是任何类型 // 语法:let Array: Array<T> = [] let arr3: Array<number | string> = [1, 2, 3, 'a']复制代码
3. ts 中定义对象
在 ts 定义对象,用到了接口(Interfaces)的概念。
// 先看看 js 中对象的定义 let obj = { // 对象中任意定义数据没有任何限制 name: '你好', age: 17, qq: '3068495230' } // 而在 ts 中,需要先定义好接口,才可声明对象 // 接口(Interfaces):可以用于对[对象的形状(Shape)]进行描述 // 接口(Interfaces)定义: interface Iperson { // ? 代表可选属性:声明在定义对象时这个属性是否定义都行 name ? : string; // 没加 ? 则代表 age 和 sex 在使用时,必须被定义,或者就会报错 age: number; sex: string; // 任意属性:声明在定义的时候,可以任意定义属性 // [任意名字: 名称类型]: 定义的数据类型 [propName: string]: any; } // 可以简单理解为受到接口的约束 // 有点像定义变量时的类型定义,不过这里是自己定义受到什么约束, // 只能定义什么类型的数据 let tom: Iperson = { // 这里不定义 name 也不会报错 name: 'tom', // 但如果不定义 age 和 sex 就会报错 age: 18, sex: 'man', // obj 对象与 action 方法不定义也不会报错 obj: {di: 1}, action: function(){ console.log(this.age) } }复制代码
三、 Ts 中定义函数
函数的定义方式还挺多的,稍微有点绕。
1. 函数定义
函数类型定义:
输入类型
返回类型
// f() 函数规定传入的 x、y 必须为数字,且返回结果也必须是数字 function f(x: number, y:number):number{ return x + y } //输出:3 f(1, 2) // 返回其他类型可以使用 联合类型 也可以使用 any function f1(x: number, y:number):any{ return x + y } //输出:3 f1(1, 2)复制代码
2. 返回值定义
没有返回值时使用 :void
// :void{函数体} function f2(x: number, y:number):void{ console.log(x, y) } // 输出:1 2 f2(1, 2)复制代码
指定返回类型
// 如果返回数组: // :数据类型[]{函数体} function f3(x: number, y:number):number[]{ return [x, y] } // 输出:[1, 2] f3(1, 2)复制代码
3. 参数默认值定义
默认值:
如果在调用函数时没有传值,则会使用默认值。
// 如果在调用函数时没有传值,则会使用默认值。 function f4(x: number, y :number = 1):number{ return x + y } // 输出:2 f4(1)复制代码
4. 可选参数定义
与对象的定义一样,再定义形参时加上 ? 表示这个参数为可选参数,在使用时可以不传入。
// ? 表示可选参数,在使用时可以不传入,前提是内部函数执行不会出问题 function f5(x: number, y :number, z ? :number):number{ console.log(z) return x + y } //输出:3 3 f1(1, 2, 3) //输出:3 f1(1, 2) //输出:报错,y 未添加数据 f1(1)复制代码
5. 使用泛型
函数也可以使用泛型进行定义,在调用函数时才进行值的类型定义。
// 使用 泛型 定义函数 function f6<T>(x: T, y: T):T[]{ return [x, y] } // 传值时定义类型 f6<number>(2, 3) f6<string | number>('a', 3) f6<any>(true, null)复制代码
6. 小实例
仔细想这样定义有没有问题?
function f7(x: string | number ): number{ // 因为字符串有长度,而数字没有,所以会报错 return x.length } // 报错 f7('abc') // 正确方式: function f8(x: string | number[] ): number{ // 字符串有长度,而数组也有长度,所以不会报错 return x.length } f7('abc')
作者:a尘ss
链接:https://juejin.cn/post/7017712437503721508