在写 TypeScript 代码时,所有的变量都需要有类型
布尔类型
最基本的数据类型就是简单的 true / false 值
const registered: boolean = false // 变量名称:变量类型
const done: boolean = Boolean(0)
复制代码
数字类型
二进制数、十进制数、十六进制数都可以用 number 类型来表示。
let decLiteral: number = 6
let goldenSection: number = 0.618
let hexLiteral: number = 0xf00d
let binaryLiteral: number = 0b1010
let octalLiteral: number = 0o744
let notANumber: number = NaN
复制代码
BigInt
JavaScript 中可以用
Number
表示的最大整数为 2^53 – 1,可以写为Number.MAX_SAFE_INTEGER
。如果超过了这个界限,可以用BigInt
来表示,它可以表示任意大的整数。
语法
const theBiggestInt: bigint = 9007199254740991n //整数字面量后加 n
const alsoHuge: bigint = BigInt(9007199254740991) //调用函数 BigInt()
const hugeString: bigint = BigInt("9007199254740991")
theBiggestInt === alsoHuge // true
theBiggestInt === hugeString // true
复制代码
BigInt 与 Number 的不同点:
- BigInt 不能用于 Math 对象中的方法。
- BigInt 不能和任何 Number 实例混合运算,两者必须转换成同一种类型。
- BigInt 变量在转换为 Number 变量时可能会丢失精度。
//number
const biggest: number = Number.MAX_SAFE_INTEGER
const biggest1: number = biggest + 1
const biggest2: number = biggest + 2
biggest1 === biggest2 // true 超过精度 无论往上加多少都会溢出,所以这两个值是相等的。
//bigint
const biggest: bigint = BigInt(Number.MAX_SAFE_INTEGER)
const biggest1: bigint = biggest + 1n
const biggest2: bigint = biggest + 2n
biggest1 === biggest2 // false 容器没满
复制代码
Number 与 BigInt 之间进行转换会损失精度,建议:
- 不要在两种类型之间进行相互转换。
- 仅在值可能大于 2^53 – 1 时使用 BigInt。
类型信息
typeof 10n === 'bigint' // true
typeof BigInt(10) === 'bigint' // true
typeof 10 === 'number' // true
typeof Number(10) === 'number' // true
复制代码
运算
BigInt 可以正常使用 +、-、*、/、**、% 符号进行运算
const previousMaxSafe: bigint = BigInt(Number.MAX_SAFE_INTEGER) // 9007199254740991n
const maxPlusOne: bigint = previousMaxSafe + 1n // 9007199254740992n
const multi: bigint = previousMaxSafe * 2n // 18014398509481982n
const subtr: bigint = multi – 10n // 18014398509481972n
const mod: bigint = multi % 10n // 2n
const bigN: bigint = 2n ** 54n // 18014398509481984n
const divided: bigint = 5n / 2n // 2n, not 2.5n 当使用 / 操作符时,会向下取整,不会返回小数部分
复制代码
比较与条件
//Number 和 BigInt 进行比较
0n === 0 // false
0n == 0 // true
1n < 2 // true
2n > 1 // true
2 > 2 // false
2n > 2 // false
2n >= 2 // true
////Number 和 BigInt 条件判断
if (0n) {
console.log('条件成立!');
} else {
console.log('条件不成立!'); // 输出结果
}
0n || 10n // 10n
0n && 10n // 0n
Boolean(0n) // false
Boolean(10n) // true
!10n // false
!0n // true
复制代码
字符串类型
//单引号或双引号
let myName: string = 'Tom';
let myAge: number = 25;
// 模板字符串
let sentence: string = `Hello, my name is ${myName}.
I'll be ${myAge + 1} years old next month.`;
// 反引号 ` 定义 ES6 中的模板字符串,${expr} 用来在模板字符串中嵌入表达式。
复制代码
any 类型
不能确定其变量类型,不希望类型检查器对这些值进行检查,可以使用 any,声明为 any 的变量可以赋予任意类型的值
let input: any = 'nothing'
input = 0 // ok
input = true // ok
input = [] // ok
input = null // ok
input = Symbol('any') // ok
复制代码
如果一个数据是 any 类型,那么可以访问它的任意属性,即使这个属性不存在:
let anything: any = 10
anything.eat() // ok
anything.name // ok
anything[0] // ok
new anything() // ok
anything() // ok
复制代码
any 类型几乎可以做任何操作,这样很容易编写类型正确但是执行异常的代码。我们使用 TypeScript 就是为了代码的健壮性,所以要尽量减少 any 的使用。
void 类型
当一个函数没有返回值时,可以将其返回值类型定义为 void:
function doNothing(): void {
let a = 10
}
复制代码
声明一个 void 类型的变量没有什么用,因为你只能将它赋值为 undefined 和 null:
let nothing: void = undefined
复制代码
null 和 undefined 类型
undefined
和 null
是所有类型的子类型。
一般项目是默认开启 —strictNullChecks
检测的,如果你将 tsconfig.json
中 strictNullChecks
选项设置为 false
,下面这种操作不会报错,不过尽量不要这么做:
let num: number = undefined
let list: number[] = undefined
let name: string = undefined
复制代码
never 类型
never 类型表示那些永不存在的值的类型,例如, never类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型; 变量也可能是 never类型,当它们被永不为真的类型保护所约束时。
never类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是never的子类型或可以赋值给never类型(除了never本身之外)。 即使 any也不可以赋值给never。
// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
throw new Error(message);
}
// 推断的返回值类型为never
function fail() {
return error("Something failed");
}
// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
while (true) {
}
}
复制代码
unknown 类型
unknown 类型只能分配给 any 类型和 unknown 类型本身
在那些将取得任意值,但不知道具体类型的地方使用 unknown,而非 any。
let value: unknown
let value1: unknown = value // OK
let value2: any = value // OK
let value3: boolean = value // Error
let value4: number = value // Error
let value5: string = value // Error
let value6: object = value // Error
let value7: any[] = value // Error
复制代码
unknown 类型在被确定为某个类型之前,不能被进行诸如函数执行、实例化等操作,一定程度上对类型进行了保护:
let value: unknown
value.foo.bar // Error
value.trim() // Error
value() // Error
new value() // Error
value[0][1] // Error
复制代码
数组类型
//元素类型后接上 []:
let list: number[] = [1, 2, 3]
let names: string[] = ['Sherlock', 'Watson', 'Mrs. Hudson']
//数组泛型,Array<元素类型>:
let list: Array<number> = [1, 2, 3]
let names: Array<string> = ['Sherlock', 'Watson', 'Mrs. Hudson']
let list: any[] = ['Sherlock', 1887] //混合各种元素类型
复制代码
Symbol
symbol 类型的值是通过 Symbol 构造函数创建的。每个从 Symbol() 返回的 symbol 值都是唯一的。
let sym2 = Symbol("key");
let sym3 = Symbol("key");
sym2 === sym3; // false, symbols是唯一的
复制代码
object 类型
object表示非原始类型,也就是除number,string,boolean,symbol,null或undefined之外的类型。
let obj: object
// 枚举类型
enum TokenType {
ACCESS = 'accessToken',
REFRESH = 'refreshToken'
}
obj = TokenType
obj = [1, 2, 3]
obj = [1, 'string'] // 元组类型
obj = { a: 1 }
复制代码
可以看到枚举、数组、元组和普通对象都是 object 类型。
注意
- TypeScript 中描述类型要用 小写。比如 boolean、number、string等;
- 不要滥用 any ;
- 大写开头的如 Boolean、Number、String 代表的是 JavaScript 的构造函数:
let a: Number = new Number('10') // a === 10 为 false
// 通过 new Number('10') 得到的是一个构造函数,本质是一个对象
let b: number = Number('10') // b === 10 为 true
// Number('10') 与 10 都是声明一个数字 10 的方法,本质就是一个数字
a instanceof Number // true
b instanceof Number // false
复制代码