typescript基础篇(2):数据类型
2. 数据类型
Ts在es 6基础上加了不少类型。同时还弄出了不少玩法。本章从基础数据类型开始讲起
注意:在ts中,定义数据类型,除了Function,其它全部都是开头小写。
2.1 基本类型
在helloworld案例中,就已经使用了类型注解,相当于强类型语言中类型声明:
let greeting = (person: string) => `Hello, ${person}` // 参数person必须为字符串
基本的语法是:
(变量/函数):type
2.1.1 简单基础类型
对于最基础的数据类型:
// 原始类型
let bool: boolean = true
let bool2:boolean = 'true' // 报错
let num: number = 123
let str: string = "123" // 等价于 let str = '';
如果你不按照规矩进行赋值,就要报错。
2.1.2 数组
如果你要定义一个数组,你可以这么操作:
// 完全由数字组成的数组,二者等价
let arr1: number[] = [1, 2, 3]
let arr2: Array<number> = [1, 2, 3]
// 由数字 或 字符串组成的数组
let arr3: Array<number | string> = [1, "2", 3]
2.1.3 元组
元组可以理解为是一种规定了数组长度和对应元素类型的特殊数组,它的定义也类似:
// 元组类型:限定了数组成员的类型和个数
let tuple:[number,string]= [1,'2']
let tuple: [number, string] = ["1", "2"] // 报错:Type 'string' is not assignable to type 'number'.
let tuple: [number, string] = [1, "2",3] // 报错:Types of property 'length' are incompatible.Type '3' is not assignable to type '2'.
但是,如果你对元组进行push,就不报错了。(实际开发强烈不建议这么骚操作)
let tuple: [number, string] = [1, "2"]
tuple.push(3) // 不报错
console.log(tuple) //[1,'2',3]
tuple[2] // 越界访问报错!
2.1.4 函数
我们用es6的习惯写一个加法函数:
const add = (x, y) => x + y
这种实践是不好的,因为x,y都有可能是任何数据类型(any)。直接相加是要出问题的。所以解决方案是:
const add = (x: number, y: number) => x + y // 限定入参必须为数字
const add2 = (x: number, y: number): number => x + y // 限定返回值也必须为数字s
2.1.5 对象
假如我们在ts中这么定义了一个对象:
const obj: object = {
x: 1,
y: 2,
}
obj.x = 3 // 警告:obj上未定义属性'x'
所以,你应该写明白obj上x和y的属性:
const obj: { x: number; y: number } = { x: 1, y: 2 }
obj.x = 3
2.1.6 symbol
symbol的含义就是:具有唯一的值:
const s1: symbol = Symbol()
const s2 = Symbol()
console.log(s1 === s2) // false
2.1.7 其它数据类型
在ts的定义中,undefined和null是任何其它数据类型的子类型,按理来说类似这种操作是应该允许的:
let aaa: number = 1
aaa = undefined
结果报错了。这时就应该去配置项tsconfig
中设置strictNullChecks:false
let aaa: number|undefined = 1
aaa = undefined
在js中你可以声明undefined
这个变量。
// 浏览器环境下
(function(){
const undefined = 0;
console.log(undefined);
})()
// 0
那么在这个闭包中,undefined就是0。
js中void是一种操作符,在ts中,返回真正的undefined
。
还有一个很出名的就是any类型,表示被赋值什么类型都可以。(实现了js的功能。不建议)
never类型:一下两种情况,返回never,表示永远不会有返回值:
const err = () => {
throw new Error("err")
}
const endless = () => {
while (true) {}
}
2.2 枚举类型(enum)
假设有一个用户登录系统,根据角色来显示不同的界面。我们用传统js的思维写一段判断角色的逻辑:
const initByRole = role => {
if (role === 1 || role === 2) {
// do sth
} else if (role == 3 || role == 4) {
// do sth
} else if (role == 5) {
// do sth
} else {
// do sth
}
}
这段代码问题明显:
1.可读性极差:没有文档基本没人敢改。2.硬编码问题:如果要改,改动肯定很大。
如果到了ts,可以用枚举类型来处理这种场景。
所谓枚举类型者,就是一组有名字的常量组合。比方说手机通讯录:
•张三->10086•李四->10010
我打电话给张三时,直接从通讯录检索器名字即可,很少一个个按键拨电话。当然你想通过电话来找人,也是可以的。
2.2.1 数字枚举
在ts中,可以使用数字枚举来定义5个角色的映射
// 数字枚举
enum Role {
Reporter, // 0
Developer, // 1
Maintainer, // 2
Owner, // 3
Guest, // 4
}
// Role.Reporter -> 0
// Role[0] -> Reporter
有了枚举类型,你可以通过属性来索引,也可以通过值来索引。
如果你尝试打印,发现这些其实都是普通的的Object对象:
它的编译过程是:
var Role;
(function (Role) {
Role[Role["Reporter"] = 0] = "Reporter";
Role[Role["Developer"] = 1] = "Developer";
Role[Role["Maintainer"] = 2] = "Maintainer";
Role[Role["Owner"] = 3] = "Owner";
Role[Role["Guest"] = 4] = "Guest";
})(Role || (Role = {}));
就是反向映射。
2.2.2 字符串枚举
对于枚举类型,完全可以人工定义:
enum Msg {
success = "成功",
Fail = "失败",
}
再看看编译结果:
var Msg;
(function (Msg) {
Msg["success"] = "u6210u529F";
Msg["Fail"] = "u5931u8D25";
})(Msg || (Msg = {}));
显然无法做到根据"成功"索引success——也就是说,对于字符串枚举,是没法做到反向映射的。
2.2.3 异构枚举
当然你可以字符串和数字放在一个枚举对象,称之为异构枚举。
enum Aaa {
a = 1,
b = "1",
}
编译结果
(function (Aaa) {
Aaa[Aaa["a"] = 1] = "a";
Aaa["b"] = "1";
})(Aaa || (Aaa = {}));
很明显这种操作很容易混淆,也是不建议使用的。
2.2.4 枚举类型的性质
•枚举成员的值,是不能修改的。(只读)•对于枚举类型,定义值有几种情况:•没有定义值。•对其它枚举属性的引用。•常量表达式:编译时被计算出来。•非常量表达式:如arr.length:编译时被保留•常量枚举:比如
const enum Month{
Jan=1,
Feb=2,
Mar=3
}
是不会被编译的。那又有什么意义呢?
可以引用常量枚举的表达式,虽然编译不存在这个Month对象,但通过常量枚举,减少了代码的复杂度。
const enum Month {
Jan = 1,
Feb = 2,
Mar = 3,
}
let month = [Month.Jan, Month.Feb, Month.Mar]
console.log(month)
编译结果为:
var month = [1 /* Jan */, 2 /* Feb */, 3 /* Mar */];
console.log(month);
•枚举类型和枚举成员都可以作为类型来定义。枚举类型不同的枚举值,不可项目比较。
- MySQL访问受限的问题分析
- 一个Oracle监听问题的网络排查
- MySQL InnoDB Cluster环境搭建和简单测试
- 多平台下的数据存储新秀-PROTOBUF
- TCP的长连接与短连接的含义与区别(附Java代码实现)
- Mycat读写分离配置实践
- 快速搭建主从的脚本和问题排查
- MySQL在RR隔离级别下的unique失效和死锁模拟
- Golang语言--glog日志库使用
- 一个MySQL死锁问题的复现
- Spring Boot 2.0 新特性(一):配置绑定 2.0 全解析
- MySQL断电恢复的一点简单分析
- Spring Boot 2.0 新特性(二):新增事件ApplicationStartedEvent
- 奇怪的go语言iota
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 前端学数据结构与算法(五):理解二叉树特性及从零实现二叉搜索树
- 前端学数据结构与算法(四):理解递归及拿力扣链表题目练手
- 前端学数据结构与算法(三):链表为什么能和数组相提并论?用链表实现数组bettle下
- 前端学数据结构与算法(二):数组的操作特性与栈的应用
- 前端学数据结构与算法(一):不会复杂度分析,算法等于白学
- 高可扩展性系统的设计
- Vue如何实现导出页面为PDF
- 短视频APP开发,如何做到获取播放视频和音频文件
- 3分钟短文:Laravel模型创建数据条目的2个语法糖
- leetcode队列之最近的请求次数
- 路由策略中的IP-Prefix你了解多少?
- Qt音视频开发29-Onvif云台控制
- 十大高性能开发
- 【云+社区年度征文】java agent及字节码技术得到DNS时间流程尝试
- 短视频商城源码,制作彩色验证码