Skip to content

数据类型

一、基本类型

ts
//字符串
let str: string = "Domesy"
// 数字
let num: number = 7
//布尔
let bool: boolean = true
//symbol
let sym: symbol = Symbol();
//bigint
let big: bigint = 10n
//null
let nu: null = null
//undefined
let un: undefined = undefined
  • symbol是独一无二的,假设再定义一个 sym1,那么sym === sym1 为 false

二、引用类型

2.1 Array

定义数组方式有两种:

  • 类型名称 + []
  • Array<数据类型>
ts
let arr1: number[] = [1, 2, 3]

let arr2: Array<number> = [1, 2, 3]
//要想是数字类型或字符串类型,需要使用 |
let arr3: Array<number | string> = [1, 2, '3']

2.2 Tuple(元组)

Tuple 的作用就是限制元素的类型并且限制个数的数组

ts
let t: [number, string] = [1, '2']
// error
let t3: [number, string] = [1, '1', true]
// 只能通过 push 进行扩增
let t5: [number, string] = [1, '2'] // ok
t.push(2)

2.3 object(对象)

object 非原始类型,可以在定义上直接使用 object

ts
let obj1: object = { a: 1, b: 2}
obj1.a = 3 // error

但你要更改对象的属性就会报错,原因是并没有使对象的内部具体的属性做限制,所以需要使用 {} 来定义内部类型

ts
let obj2: { a: number, b: number } = {a: 1, b: 2}
obj2.a = 3 // ok

对象的类型标注

但在实际开发中,我们一半会用到 interface 来实现对象对外提供的接口结构。

ts
interface User {
    name: string;
    age: number;
}

const user1: User = {
    name: '张三',
    age: 18
}

2.4 function

ts
// 没有定义返回类型情况下 默认是 void,如果函数中有 return ,那么TS会自动推断
function setName1(name: string) {
    console.log("hello", name)
}
// 定义返回类型
function setName2(name: string):string {
    return name
}
  • 支持 ? 实现可选参数
  • 支持其它高级的 ES+ 语法,比如 = 设置默认值,使用扩展运算符 ...

三、特殊类型

3.1 any

在 TS 中,任何类型都可以归于 any 类型,所以any类型也就成了所有类型的顶级类型

ts
let d:any
d = '1'
d = 1
// ...

3.2 unknow

与 any 一样,都可以作为所有类型的顶级类型,但 unknow 更加严格,那么可以说除了any 之下的第二大类型,接下来对比下 any ,主要严格于一下两点:

  • unknow 会对值进行检测,而类型 any 不会做检测操作,说白了,any 类型可以赋值给任何类型,但 unknow 只能赋值给unknow类型和any类型
  • unknow 不允许定义的值有任何操作(如 方法,new等),但any可以
ts
let u:unknown = '1'
let str: string = u // error

3.3 void

当一个函数,没有返回值时,TS会默认他的返回值为 void 类型

3.4 never

表示一个函数永远不存在返回值,TS会认为类型为 never。那么与 void 相比, never应该是 void子集, 因为 void 实际上的返回值为 undefined,而 never 连 undefined也不行

符合never的情况有:当抛出异常的情况和无限死循环

ts
let error = ():never => { // 等价约 let error = () => {}
    throw new Error("error");
}

let error1 = ():never => {
    while(true){}
}

四、装箱类型

Object(大写的O)是装箱类型,代表所有的原始类型或非原始类型都可以进行赋值,除了null和`undefined

ts
let obj: Object;
obj = 1 // ok
obj = "a" // ok
obj = true // ok
obj = {} // ok
obj = Symbol() //ok
obj = 10n //ok
obj = null // error
obj = undefined // error

和 Object 类似的还有 Boolean、Number、String、Symbol,这几个装箱类型(Boxed Types) 同样包含了一些超出预期的类型。以 String 为例,它同样包括 undefined、null、void,以及代表的 拆箱类型(Unboxed Types) string,但并不包括其他装箱类型对应的拆箱类型,如 boolean 与 基本对象类型,我们看以下的代码:

ts
const tmp9: String = undefined;
const tmp10: String = null;
const tmp11: String = void 0;
const tmp12: String = 'linbudu';

// 以下不成立,因为不是字符串类型的拆箱类型
const tmp13: String = 599; // X
const tmp14: String = { name: 'linbudu' }; // X
const tmp15: String = () => {}; // X
const tmp16: String = []; // X

在任何情况下,你都不应该使用这些装箱类型。

五、类型断言

有时候你很清楚改值是什么类型的时候,可以直接使用类型断言告诉编译器。这在开发时某些情况下很好用。
使用类型断言

js
let strLength: number = (<string>someValue).length

let strLength: number = (someValue as string).length

这里推荐使用 as 写法。

六、字面量类型

直接把值当作数据类型为字面量类型

ts
const str: "zhangsan" = "zhangsan"

单一看字面量类型好像没什么用,一般会与联合类型一起使用。

七、联合类型

联合类型与枚举有点相似,就是列出特定的值,该变量的值只能从中获取。例如与上面的字面量类型相结合

ts
interface User {
    name: '张三' | '李四';
    age: number
}

const user1: User = {
    name: '张三',
    age: 14
}

八、枚举

在 TypeScript 中通过 enum 来定义枚举数据

ts
enum Direction {
    Up = 'Up',
    Down = 'Down',
    Left = 'Left',
    Right = 'Right',
}

console.log(Direction.Up) // Up

如果不指定值的话,那么默认就是从 0 开始递增

九、类型别名

类型别名起到的就是变量的作用,它可以存储一个类型,后续你可以直接引用它即可。

ts
// 简单类型的类型别名
type myNumber = number
const time: myNumber = 10

// 对象类型的类型别名
type Uesr = {
    name: string;
    age: number;
}
const user: User = { /* ... */ }

注意:起别名不会新建一个类型 - 它创建了一个新名字来引用那个类型。给基本类型起别名通常没什么用。类型别名常用于联合类型。

十、交叉类型

交叉类型是将多个类型合并为一个类型。 这让我们可以把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性。

ts
interface People {
    name: '张三' | '李四'
    age: number
}

interface Man {
    header: string
    body: string
}

const user: <People & Man> = {
    name: '张三',
    age: 21,
    header: '圆头',
    body: '强壮'
}