TypeScript进阶(一):变量及函数定义
文章目录
- 一、前言
- 二、变量定义
- 三、函数定义
- 3.1 函数参数约束
- 3.2 函数返回值约束
- 四、拓展阅读
一、前言
TypeScript
(TS)是微软开发的开源编程语言,为JavaScript的超集,用于设计开发大型应用,其可以编译出纯净、 简洁的JavaScript
代码,并且可以运行在任何浏览器上、Node.js环境中和任何支持ECMAScript 3(或更高版本)的JavaScript引擎中。TypeScript提供最新的和不断发展的JavaScript特性,包括那些来自2015年的ECMAScript和未来的提案中的特性,比如异步功能和Decorators,以帮助建立健壮的组件。
两者之间存在一些区别,主要是:
- 后缀文件不同,TS文件后缀为
.ts
; - JS是弱类型语言,在语法上JS是动态类型语言,而TS是强类型语言,在语法上是静态类型语言。
类型(type)指的是一组具有相同特征的值,比如数值类型、字符串类型,在运算过程中只能数值类型和数值类型进行求和运算,而不能和字符串类型求和。
但是JS语言的类型系统比较弱,使用起来也没限制,比如一个变量x定义时,定义为数值123,但是在后面也可以直接修改其值为"abc",这样就直接将数值类型改为了字符串类型,所以JS是动态类型。而TS中使用了更严格的类型系统,当变量X被定义时需要添加类型声明,被预先声明为数值型123后,就不能赋值为"abc",变量的类型是静态的。TS的使用,为JS引入了静态类型特征。
静态类型有一定的优点和缺点。优点包括:
- 有利于代码的静态分析和发现错误;
- 更好的IDE支持,便于代码补全和语法提示;
- 有利于提高代码质量,保证代码安全,适合在大型项目中使用。
缺点为丧失了动态类型的代码灵活性,增加了编程的工作量和学习成本,过去的一些JS项目可能也会存在兼容性问题,所以TS不一定适合那些小型、短期项目。
类型声明与类型断言
在TS中定义变量时,可以进行声明变量类型后,赋值再使用。
// TypeScript代码:有明确的类型,即: number (数值类型)
let age: number = 18
// JavaScript代码:无明确的类型
let age = 18
TS相比于JS的优势
JS的类型系统存在"先天缺陷”, 绝大部分错误都是类型错误( Uncaught TypeError
)。TS相比于JS,存在如下优势:
- 类型化思维方式,使得开发更加严谨,提前发现错误,减少改Bug时间。
- 类型系统提高了代码可读性,并使维护和重构代码更加容易。
- 补充了接口、枚举等开发大型应用时JS缺失的功能。
Vue 3
源码使用TS重写,释放出重要信号: TS是趋势。
Angular
默认支持TS;
React
与TS美配合,是很多大型项目的首选。
二、变量定义
TS继承了JS的一些类型,所以TS的基本类型包括:string
、number
、object
、null
、boolean
、bigint
、symbol
、undefined
。其中,null
和undefined
既是值,又是类型。这里需要注意的是都是小写字母,大写的Number
、String
等在JS中属于内置的对象。
在TS中还有联合类型union types
,指的是多个类型组合成一个新的类型,使用符号|
。如下例子所示,将联合类型和定义类型别名一起使用,只要一个类型属于string或者number,那么就是属于联合类型T。
type T = number | string;
let x1: T = 123;
let x2: T = "abc";
console.log(x1);
console.log(x2);
// 也可以不使用类型别名
let x3: string | number;
x3 = 123;
console.log(x3);
x3 = "abc";
console.log(x3);
- 布尔类型
//布尔类型
let isTrue:boolean = true;
let isFalse:boolean = false;
console.log(isTrue)
console.log(isFalse)
- 数字类型
//数字类型
let size:number = 18;
let score:number = 99.8;
let sub:number = - 100;
console.log(size)
console.log(score)
console.log(sub);
- 字符串类型
//字符串类型
let pname:string = '1874009';
console.log(pname);
//模板字符串
let age:number = 18;
let str:string = `${pname}的年龄是${age}岁!`;
console.log(str)
- 数组类型
TS数组与JS数组最大的不同,是需要保证成员的类型一致,但是成员的数量也是不确定的。这里数组的类型也可以使用联合类型。
// 两种方式,约束数组为数值类型
let arr: number[] = [1,2,3];
let arr: Array<number> = [1, 2, 3];
//联合类型,第一种方式必须使用括号
let arr: (number|string)[];
//语法二:泛型
let arr:Array<number|string>;
// 不设置数组成员类型,但是需要避免使用
let arr:any[];
示例:
let arr: (number | string)[];
arr = [1, 2, 3];
arr[3] = "abc";
console.log(arr);
- 元组类型
元组(tuple
)是TS新增的数据类型,JS没有这种类型,它表示成员类型可以自由设置的数组,即数组的各个成员的类型可以不同;元组成员的类型可以添加问号后缀?
,表示该成员是可选的,但是问号只能用在元组尾部的成员身上,所有可选成员必须在必选成员之后。
//元组类型(通过元组类型可以给数组中的元素指定多个数据类型)
let tuple:[string,number,boolean] = ['1874009',18,true];
console.log(tuple);
// 元组,元组结构的声明;可以使用问号设置为某个值为不必须输入
let t1: [number, string, number?]=[1,"a"]
- 枚举类型
枚举也是TS新增数据类型,但是它也是一个值,其将相关的常量等放在一起便于使用和调用。调用enum
的成员可以使用点运算符或者方括号。
// 定义一个枚举结构
enum Color {
red,
blue,
green,
}
//等同于如下JS结构
var Color;
(function (Color) {
Color[Color["red"] = 0] = "red";
Color[Color["blue"] = 1] = "blue";
Color[Color["green"] = 2] = "green";
})(Color || (Color = {}));
// 调用
let c1 = Color.blue;
let c2 = Color["red"];
console.log(c1);
console.log(c2);
在上面的例子中,声明了一个 Enum 结构Color,里面包含三个成员red、blue和green。第一个成员的值默认为整数0,第二个为1,第二个为2,以此类推。而调用 后,c1和c2并不是具体的颜色,而是1和0。
7. 任意类型 (any) (获取dom节点)
```typescript
var num:number = 19;
num = 20; //报错
var num:any = 20;
num = 99;//不会报错
null
和undefined
(都只有一个值,并且值为它本身。)
//用来定义可能为未赋值又需要赋值的数字
var num:undefined | number;
console.log(num)
//一个元素可能是number类型 可能是null 可能是undefined
var num:number | undefined | null;
- void类型(一般用于定义方法没有返回值)
//ES5 没有返回值的函数
function run():void{
console.log('run')
}
run();
function run2():number{
return 123
}
run2();
- never类型(声明never的变量只能被never类型所赋值)
var a:never;
a = () => {
throw new Error('错误');
}
三、函数定义
TS中函数定义和JS是一模一样的,可以是普通函数声明,也可以函数表达式。
函数签名=函数名称+函数参数+函数参数类型+返回值类型。
// 1.函数声明法
function fun(): string {
return '123'
}
// 2.匿名函数法
let fun2 = function (): number {
return 123
}
// 3.没有返回值的方法
function fun3(): void {
console.log(111);
}
函数传参方法
TS 里可以自定义传入参数的类型以及函数返回的类型。
function getInfo(name: string, age: number): string {
return name + age
}
console.log(getInfo('zs', 20));
可选参数
TS 函数还可以设置可选参数。如果不设置可选参数,那么所有定义的参数都要传入,在参数后边加一个?
号表示该参数可传可不传。
注意⚠️:可选参数必须配置到参数的后面!
function fun(name: string, age?: number): string {
if (age) {
return name + age
} else {
return name + '年龄未知'
}
}
fun('zs')
fun('ls', 29)
默认参数
当函数设置了默认参数时,如果给函数传值,所传过来的值会覆盖设置的默认值,未传值时选择默认值,这个其实也是 ES6 的特性,可以给函数加默认参数值。
要注意的是:设置默认值后就不需要设置类型了,因为 TS 可以做类型推断。
function fun(name: string, age: number = 29): string {
if (age) {
return name + age
} else {
return name + '年龄未知'
}
}
fun('zs')
fun('ls', 30)
剩余参数
当函数不知道要传递多少个参数的情况下,可以使用三点运算符(…
),这是函数里类似数组的一个特殊对象,里面存放的是函数传入参数,很好理解。
注意⚠️:不是数组,是对象,只是长得像数组。
function fn(a: number, ...args: number[]) {
// rest (剩余部分)参数必须是数组类型
let res = 0
args.forEach(item => {
res += item
})
return res
}
console.log(fn(1, 2, 3, 4, 5))//14
但是在TS中针对函数做了很多的约束,包括函数参数约束、函数返回值约束。
3.1 函数参数约束
对函数形参进行了约束,在传递值的时候,就必须按照指定的参数类型传递。
- 参数个数必须满足要求;
- 每个位置参数,数据类型一定要匹配;
参数是数字和字符串时:
// 普通函数定义
function show(params:number,params2:string){
console.log(params);
console.log(params2);
}
show(1,"xiaowang")
参数是对象/数组时:
const play = (user: { id: number }) => {
console.log(user.id);
}
play({ id: 1 })
const play2 = (stus:string[]) => {
console.log(stus);
}
play2(["1","2"])
参数是可变参数时:
const play3 = (params:number,...params2:number[]) => {
console.log(params); // 1
console.log(params2); // [2,3,4,5,6,7,8]
}
// 表示可变参数:参数的个数可以动态变化
play3(1,2,3,4,5,6,7,8)
3.2 函数返回值约束
在TS中,定义每个函数都应该有返回结果。
就算函数不需要返回,也应该告诉调用者,当前函数没有返回结果。
// void代表当前函数没有返回结果,不写默认编辑器添加
function eat(num1:number):void{
console.log(num1);
return;
}
eat(10)
function eat2(num1:number,num2:number):string{
const result:string = num1 + num2 + "";
return result
}
const total2:string = eat2(20,30)
四、拓展阅读
- 《TS中文官网》
- 《TS练习官方》
- 《 阮一峰 TypeScript 教程 (p6p.net)》