TypeScript学习笔记 其二
TypeScript学习笔记 其二
学习React时发现TS是一个绕不过去的坎儿,所以打算趁着春节有时间顺便系统的学习一下TS😄。。
第二篇整理了TypeScrip相关的数据类型,并根据它们不同的特性写了demo。
该系列目录:
第一篇:TypeScript学习笔记 其一
第二篇:TypeScript学习笔记 其二
....待续....
数据类型
在ES6中有六种基本数据类型:Boolean、Number、String、Symbol、undefined、null;三种引用类型:Array、Function、Object。
TypeScript在ES6的基础上又新增了几种类型:void、any、never、元组、枚举
ES6的数据类型 | TypeScript中和ES6一致的数据类型 | TypeScript中新增的数据类型 |
---|---|---|
Boolean | Boolean | void |
Number | Number | any |
String | String | never |
Symbol | Symbol | 元组 |
undefined | undefined | 枚举 |
null | null | |
Array | Array | |
Function | Function | |
Object | Object |
各数据类型的定义
首先介绍个概念:类型注解,作用相当于强类型语言的类型声明,可以对声明类型的变量或函数起到类型约束作用;语法为(变量/函数) : type
在上节的index.ts中我们写了一行代码:let hello : string = "Hello TypeScript"
,就是声明变量hello的类型为string。
以下示例均可在TypeScript国内官网的在线运行测试网页中测试
-
Boolean: 表示逻辑值:true 和 false。例:
let bool: boolean = true
-
Number: 双精度 64 位浮点值。它可以用来表示整数和分数。例:
let decLiteral: number = 666
-
String: 一个字符系列,使用单引号(')或双引号(")来表示字符串类型。反引号(
`
)来定义多行文本和内嵌表达式。例:let myName: string = "AzumaTokaku"
-
undefined和null: undefined用于初始化变量为一个未定义的值;null表示对象值缺失。例:
let un: undefined = undefined; let nu: null = null
;值得注意的是,ts中默认严格校验类型约束,如这种情况会报错Type 'null' is not assignable to type 'number'.
和Type 'undefined ' is not assignable to type 'number'.
,只有在tsconfig.json中设置strictNullChecks为false,才会正常编译。如果不设置strictNullChecks为false,也可以声明num为多个类型:let num: number | undefined | null = 123
,这样也可以通过类型约束检查。let num: number = 123 let un: undefined = undefined let nu: null = null num = undefined num = null
-
Symbol: 表示独一无二的值,常用来定义对象的唯一属性名。在实例中,s1和s2虽然创建过程一模一样,但是并不相等。不通过Symbol.for()方法创建的变量无法通过Symbol.keyFor()方法取值。Symbol.for() 类似单例模式,会在全局中搜索被登记的Symbol中是否有该参数作为名称的Symbol值,如果有即返回该Symbol值,若没有则新建并返回一个以该参数为名称的Symbol值,并登记在全局环境中供搜索。Symbol.keyFor()只能返回一个已登记的Symbol类型值的key。
let s1: symbol = Symbol("kk") console.log(Symbol.keyFor(s1)) let s2: symbol = Symbol("kk") console.log(s1 === s2) s1 = Symbol.for("Yannis"); console.log(s1) console.log(Symbol.keyFor(s1))
- void: 用于标识方法返回值的类型,表示该方法没有返回值。例:
let noReturn = (): void=> {return 1 + 1};
如果return值,会报Type 'number' is not assignable to type 'void'.
。由于undefined在js中并不是保留字有可能会被赋值替换,所以有时也会用void 0
表示undefined。
- any: 类型声明为any的变量可以赋予任意类型的值。一般不使用,用了any就没有使用TypeScript进行类型约束的意义。
- never: never类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是never的子类型,也就没有任何类型可以赋值给never类型(除了never本身之外), 即使 any也不可以赋值给never。在函数中它通常表现为抛出异常或无法执行到终止点(例如无限循环)。
let x: never;
let y: number;
// 运行错误,数字类型不能转为 never 类型
x = 123;
// 运行正确,never 类型可以赋值给 never类型
x = (()=>{ throw new Error('exception')})();
// 运行正确,never 类型可以赋值给 数字类型
y = (()=>{ throw new Error('exception')})();
// 返回值为 never 的函数可以是抛出异常的情况
function error(message: string): never {
throw new Error(message);
}
// 返回值为 never 的函数可以是无法被执行到的终止点的情况
function loop(): never {
while (true) {}
}
- 数组: 使用单独的变量名来存储一系列的值。
// 两种声明方式
let arr1: number[] = [1, 2, 3]
let arr2: Array<number> = [1, 2, 3]
// 联合类型声明,数组的值既可以是number类型也可以是string类型
let arr3: Array<number | string> = [1, 2, 3, '4']
- 元组: 表示一个已知元素数量和类型的数组,各元素的类型不必相同。
// 元组
let tuple: [number, string] = [0, '1']
// 元组的越界问题,可以使用push方法往元组中插入新元素
tuple.push(2)
// 打印结果[0, "1", 2],会发现元素已经插入进去了
console.log(tuple)
// 但是元组不允许访问越界插入的新元素
tuple[2]
-
函数: 函数是JavaScript应用程序的基础。 它帮助你实现抽象层,模拟类,信息隐藏和模块。 在TypeScript里,虽然已经支持类,命名空间和模块,但函数仍然是主要的定义行为的地方。
// add函数的x,y参数声明为number类型,返回值也声明为number类型;不过通常函数的返回值可以省略,TypeScript会自动推断类型,这叫做“按上下文归类”,是类型推论的一种。 let add = (x: number, y: number) : number => x + y // let add = (x: number, y: number) => x + y // 定义一个compute函数类型,但是没有具体实现 let compute: (x: number, y: number) => number // 实现compute函数类型,在实现过程中可以不指定具体的类型 compute = (a, b) => a + b
-
对象: object表示非原始类型,也就是除number,string,boolean,symbol,null或undefined之外的类型。
let obj1: object = { x: 1, y: 2 } // 报错:Property 'x' does not exist on type 'object'. obj1.x = 3 let obj2: { x: number, y: number } = { x: 1, y: 2 } // 正常编译 obj2.x = 3
枚举
枚举: 一组有名字的常量集合。枚举类型被编译成一个对象,它包含了正向映射( name -> value)和反向映射( value -> name)。 引用枚举成员总会生成为对属性访问并且永远也不会内联代码(字符串枚举除外)。
// 数字枚举,默认从0开始,即Role.Reporter的值为0,后面的值依次递增
enum Role {
Reporter,
Developer,
Maintainer,
Owner,
Guest
}
//Role.Reporter值为0
console.log("数字枚举:" + Role.Reporter);
//数字枚举的反向映射
let reporter = Role.Reporter;
console.log("数字枚举的反向映射:" + Role[reporter]);
// 数字枚举,可设置初始值,即Role.Reporter的值为1,后面的值依次递增
enum Role {
Reporter = 1,
Developer,
Maintainer,
Owner,
Guest
}
//Role.Developer值为2
console.log("设置初始值的数字枚举:" + Role.Developer);
// 字符串枚举
enum Message {
Success = '恭喜你,成功了',
Fail = '抱歉,失败了'
}
console.log("字符串枚举:" + Message.Success);
// 异构枚举,数字枚举和字符串枚举同时使用,一般不推荐这样做,容易混淆
enum Answer {
N,
Y = 'Yes'
}
// Answer.N值为0
console.log("异构枚举:" + Answer.N);
// Answer.Y值为Yes
console.log("异构枚举:" + Answer.Y);
// 常量枚举,用const声明的枚举就是常量枚举;常量枚举在编译阶段会被移除,常量枚举不允许包含需要被计算的枚举成员。当不需要一个对象,只需要对象的值时,可以使用常量枚举;这样可减少编译阶段的代码
const enum Month {
Jan,
Feb,
Mar
}
// 编译后枚举会被直接替换成常量,运行时的代码会变得简洁
let month = [Month.Jan, Month.Feb, Month.Mar]
枚举成员的性质:
- 枚举成员的值为只读类型,定义后不可修改。
- 枚举成员分为两种:常量枚举成员(const member)和需要被计算的枚举成员(computed member)
- 常量枚举成员包括三种情况:没有初始值的枚举成员、对已有枚举成员的引用、常量表达式;常量枚举成员会在编译的时候计算出结果,然后以常量的形式出现在运行环境。
- 需要被计算的枚举成员是一些非常量的表达式, 需要被计算的枚举成员不会在编译的阶段计算,会被保留到程序的运行阶段才进行计算。
- 在需要被计算的枚举成员后面的枚举成员一定要赋初始值
enum Char {
// 常量枚举成员 const member
a,
b = Char.a,
c = 1 + 3,
// 需要被计算的枚举成员 computed member
d = Math.random(),
e = '123'.length
}
枚举类型: 在某些情况下,枚举和枚举成员都可以作为类型存在;枚举类型可以分为三种情况:
- 枚举成员没有初始值
- 所有枚举成员为数字类型
- 所有枚举成员为字符串类型
// 枚举类型三种情况:
// 枚举成员没有初始值
enum E { a, b }
// 所有枚举成员为数字类型
enum F { a = 0, b = 1 }
// 所有枚举成员为字符串类型
enum G { a = 'apple', b = 'banana' }
// 可以把任意的数字赋值声明为E、F枚举类型的变量
let e: E = 3
let f: F = 3
// 枚举类型不同的变量不可进行比较,会报错
console.log(e === f)
// 枚举成员也可做为类型声明给变量
let e1: E.a = 3
let e2: E.b = 3
let e3: E.a = 3
// 枚举类型不同的变量不可进行比较,会报错
console.log(e1 === e2)
// e1和e3枚举类型相同,可进行比较
console.log(e1 === e3)
// 声明为字符串枚举类型的变量,值只能为枚举成员的值
let g1: G = G.a
// 声明为字符串枚举成员类型的变量,值只能为它自己的值
let g2: G.a = G.a
标题:TypeScript学习笔记 其二
作者:AzumaTokaku
地址:https://www.azumatokaku.cc/articles/2022/01/26/1643201667912.html