写在前面:
因为typescript文档个人感觉并不友善(概念过于杂乱,示例代码有错误~)。所以个人学习笔记总结,并不涉及typescript各种历史和一些什么javascript超集啊之类的介绍。
想学习typescript的朋友可以快速扫两眼,入个门~基础数据类型:
首先typescript的十二种基础数据类型:
布尔类型(boolean)
数字类型(number)
字符串类型(string)
数组类型(array)
元组类型(tuple)
枚举类型(enum)
任意值类型(any)
null 和 undefined
void类型
never类型
object 类型
Symbol 类型
类型断言
布尔类型(boolean)
布尔类型是最简单的数据类型,只能赋值为true
和false
两种值,不能赋予其他的值
!:类型注解: 其实就是指定各种类型, boolean, string之类的。其他语言也叫类型注解 所以统一一下
基础语法:
变量:类型注解 = 对应类型注解的值
let bol: boolean = true
let bol2: boolean
bol2 = = false
bol = blo2 // 可以 bol是boolean类型 所以可以赋值false
bol = ' 1' //Type '"1"' is not assignable to type'boolean'. 字符串不能赋值给boolean类型
复制代码
除了规定了变量类型,其他语法与javascript一样。
数字类型(number)
和JavaScript一样,TypeScript数字都是浮点型( 1 在JS眼里是 1.0),也支持二进制、八进制、十进制和十六进制
let num1: number = 123 //十进制
num1 = 0b01111011 //二进制 0b开头 ES6引入
num1 = 0o173 //八进制 0o开头 ES6引入
num1= 0x7b //十六进制 0x开头
以下是特殊的number类型:
num1 = Infinity //无穷大
num1 = -Infinity //负无穷大
num1 = NaN //Not a Number
复制代码
字符串类型(string)
被""
,''
和ES6模板字符串\` `
.包裹起来的值,都是字符串类型
let str: string = '哈哈哈'
let str2: string = `笑声${str}`
复制代码
数组类型(array)
TypeScript 提供了两种定义数组类型的方法。一种是在类型
后加上 []
表示这是一个数组。 推荐优先使用这种写法
语法:
let 变量:类型注解[]
let arr1: number[] //number类型数组,只能存number类型
arr1 = [5,1,3] // true
arr1 = ['1'] // false 只可以赋值number类型
复制代码
另一种方法是使用泛型表示:Array,其中 T 为数组中元素的类型。
语法:
let 变量:Array<T> //这里的 <T> 代指泛型。 可以简单的理解为就是一个占位符,'暂时'没有实际的类型。类型根据使用时传入的值而定。泛型后续会详解
let arr2 : Array<string> //string 数组
arr = ['1','a','haha']
let arr3 : Array<boolean> = [true,false,true] //boolean数组
复制代码
元组类型(tuple)
元组类型就是一个特殊的数组。
表示已知数量
和已知元素类型
的数组, 里面的每一项可以是不同的类型
语法:
let 变量:[类型1,类型2....]
let arr : [string, number, boolean,number[]]
//1.数量固定,只能传四个元素,不可少传也不可多传
//2.各索引位的元素类型固定,不可改变。
let numArr: number[] = [1] //普通的number数组
arr = ['1', 2, true, numArr] // true 必须按照 固定数量和类型顺序赋值
以下是错误写法:
arr = [1, 2, true, numArr] //error 第一个位置接收string类型,却传入number。类型不匹配
arr = [1, '2', true, numArr] //error 同上 ,前两个位置类型不匹配
arr = ['2'] // error arr必须接受4个参数,这里只传入一个
arr = [1, '2', true, numArr, 2] // error 传入过多的参数也不行,最后一个为越界元素。现在数组的length为4,不能传入第五个值
复制代码
枚举类型(enum)
枚举用来表示一组带有名字的常量,就是为了让一些数据更有语义化。
语法:
enum 标识符(变量) {
值,
值
...
}
------------------------------------------------------
//应用场景:假设根据后台传入数据,让我们来判断用户权限操作
//传递的数据里有id。id存储的number类型的数据,我们依次来判断
//无语义化写法:
switch(roles.id) {
case 0:
//普通用户
break;
case 1:
//员工
break;
case 2:
//管理员
break;
}
//缺点需要写文档注释,表明0 , 1...是什么意思
//使用枚举,定义一组用户数据:
enum Roles {
USER, //0
STAFF, //1
ADMIN //2
}
// 每个枚举类型的值,都有对应的索引值,默认从0开始依次递增
// 取值操作类似于JS对象
Roles.USER // 0 通过属性取索引
Roles[0] // USER 通过索引取属性值 下面会解释是如何实现的
switch(roles.id) {
case Roles.USER: // 0
//普通用户
break;
case Roles.STAFF: // 1
//员工
break;
case Roles.ADMIN: // 2
//管理员
break;
}
// 更有语义化,代码直观易读
---------------------------------------------------------------
// 在定义枚举时,可以自定义索引值
enum English {
A = 1, // 1
B, // 2
D = 4, // 4
E // 5
}
let a = English.A // 1
let c = English.B // 2
let d = English.D // 4
let e = English.E // 5
let eng = English[5] // E
//自定义索引值只会影响,后续元素的索引值(自动根据前一个增加)
enum english {
a // 默认值 0
b = 2 // 2
c // 3 根据前一个元素 +1
d = 8 // 8
e // 9
}
---------------------------------------------------------------
// 将枚举类型,转化为JS。看是如何实现的
enum Roles {
USER, //0
STAFF, //1
ADMIN //2
}
//JS代码
var Roles;
(function (Roles) {
Roles[Roles["USER"] = 0] = "USER";
Roles[Roles["STAFF"] = 1] = "STAFF";
Roles[Roles["ADMIN"] = 2] = "ADMIN"; //2
})(Roles || (Roles = {}));
解析:
首先Roles是个对象,然后立即执行函数会对这个对象进行赋值
Roles[Roles["USER"] = 0] = "USER";
可以分解为:
首先给Roles设置一个USER的属性,赋值为0
Roles["USER"] = 0 //这步操作是有返回值的 返回值就是 = 右边的值 此处为0, ~~可以测试自行创建一个对象,再赋值看返回的结果
然后将上一步的返回值作为属性名,再次赋值
Roles[0] = "USER"
所以可以通过索引或属性名取相互的值,非常巧妙
Roles[0] // USER
Roles["USER"] // 0
-------------------------------------------------------
枚举类型,后续还有很多用法。比如说使用redux时,用来存储Action的type
复制代码
any (任意类型)
any
类型就表示任意类型,一旦指定了any
类型,TS编译阶段就会通过类型检查。
let anyValue: any
anyValue = 1
anyValue = '2'
anyValue = [1,2,4,5]
// 现在变量可以任意赋值,和原生JS平时操作没有任何限制一样
--------------------------------------------------------
let anyArr: any[] = [1,24,5,'hah',['juq'],true]
//虽然方便,但尽量少使用。否者就失去了使用TS的意义,没有类型检查的保障,代码容易出问题。
复制代码
void 类型
void
表示没有任何类型, 常用在函数没有返回值的情况下指定,表示一个函数没有返回值
// 例子:
let func = (name:string):void => {
console.log(`hello, $(name)`)
// 这个函数没有指定任何返回值
// 但在JS里 函数都会默认返回undefined。void会默认兼容undefined类型
}
func(456) // error 参数必须是是string类型。这就体现了TS的好处了,编译阶段就会提醒错误
func('Bob') // true
let num:void
num = undefined //true
num = null //error
num = 1 // error
let V: any;
num = V // true 再次强调 any类型可以兼容其他所有类型(除never外)~
所以大部分场景用在函数的返回值类型上,关于函数的知识后续会讲解
复制代码
null 和 undefined 类型
1.在TS中unll
和 undefined
既是类型,也可以作为普通的值值,参考上面函数默认返回值undefined
2.在非严格模式下null
和undefined
同时也是其他类型的子类型(其他类型可以兼容这两个值), 严格模式下会报错
tsconfig.json中:strict: false (非严格模式下):
let isNull: null // null类型只能接收 null类型 和 undefined类
let isUndefined: undefined // undefined类型只能接收 undefined类型 和 null类型
isNull = null //true
isNull = 1 //error
isNull = undefined //true
isUndefined = null //true
isUndefined = undefined //true
isUndefined = '2' //error
let str: string
str = null //true
str = undefined //true
--------------------------------------------------------------
tsconfig.json中:strict: true (严格模式下):
let isNull: null // null类型只能接收null值
let isUndefined: undefined // undefined类型只能接收undefined值
isNull = null //true
isNull = 1 //error
isNull = undefined //error
isUndefined = null //error
isUndefined = undefined //true
isUndefined = '2' //error
let str: string
str = null //error 严格模式下报错,不能作为子类型
str = undefined //error
复制代码
never 类型
never
类型比较抽象,表示永远不存在的值的 类型
非严格模式下never
类型是任何类型的子类型,也可以赋值给任何类型.
//常见的两种情况 抛出错误和死循环
const errorFunc = (message: string): never => {
throw new Error(message)
}
const infiniteFunc = ():never => {
while(true){}
}
------------------------------------------------------
tsconfig.json中:strict: false (非严格模式下):
let str: string
let isNever:never
str = isNever // true
isNever = str //error
复制代码
object 类型
object
类型,就是用来表示引用类型的。与JS对象无差别
let obj = {
name: 'Bob'
}
obj.sex = 'man'
const getObject = (obj: object):void => {
console.log(obj)
}
getObject('hahah') // error
getObject(obj) // true
复制代码
类型断言
指鹿为马,把某个值,强制指定为我们需要的类型,TS就会按照我们指定的类型进行检查
可以理解为 类似于强制类型转换。只是类似┗|`O′|┛ 嗷~~
语法: 两种写法。
1. <类型>值
2. 值 as 类型 //react技术栈 编写JSX时,必须使用这个。上面的和JSX语法有歧义
// 需求 有个函数接收一个string或者number类型的值。
// 如果是string 我们直接返回字符串的长度
// 如果是number 我门把number转化为字符串,在返回长度
const getLength = (target: string | number): number => {
if(target.length) { //提示错误
return target.length //提示错误
} else {
return target.toString().length
}
}
getLength(1) // 正常
getLength('hh') //正常
//上面的代码,逻辑没有问题。但在TS中提示报错
//因为number确实没有length属性,所以TS在编译阶段就会提示错误
// 代码能正常编译为JS,但在编写TS阶段会一直提示错误.
const getLength2 = (target: string | number): number => {
// 把<string>target,把target指定为了string类型,这样代码就会按照string类型就行检测
if((<string>target).length) {
return (target as string).length //同上 第二种写法,加()是因为运算符优先级的问题
} else {
return target.toString().length
}
}
getLength2(1) //true
getLength2('hh') //true
复制代码
Symbol 类型
的讲解推荐去看阮一峰老师的ES6入门教程,TS基本上与ES6没有多大区别 除了TS扩展的类型~,所以人们常说ES6学好了,学TS会很容易