Skip to content

元组

定义

在单个变量中存储不同类型的值

特性:限制数组元素的个数和类型

都不确定使用 any[]

ts
let x: [string, number]
// 类型必须匹配且个数必须为2

x = ['hello', 10] // OK
x = ['hello', 10, 10] // Error
x = [10, 'hello'] // Error

解构赋值

ts
let employee: [number, string] = [1, 'Semlinker']
let [id, username] = employee

解构元素要小于等于元组元素个数

元素

可选元素

可选元素:通过 ? 号来声明可选元素

ts
// [variable?]
let optionalTuple: [string, boolean?]
optionalTuple = ['Semlinker', true]
optionalTuple = ['Kakuqo']

剩余元素

剩余元素:代表元组类型是开放的,有零个或多个额外的元素。

ts
type RestTupleType = [number, ...string[]]
let restTuple: RestTupleType = [666, 'Semlinker', 'Kakuqo', 'Lolo']

只读元素 ^3.4+^

可以为任何元组类型加上 readonly 关键字前缀,以使其成为只读元组。

ts
const point: readonly [number, number] = [10, 20]

使用 readonly 后,任何企图修改元组中元素的操作都会抛出异常

void

void:没有任何类型。

ts
let a: void
let b: number = a // Error

不能直接赋值,只能为它赋予nullundefined(在strictNullChecks未指定为 true 时)

方法没有返回值,定义为 void 类型,不能为 undefined

ts
function fun(): undefined {
  console.log('this is TypeScript')
}
fun() // Error

never

never:永不存在的值的类型

以下两种情况无法返回值

  1. 函数执行时抛出了异常
  2. 函数中执行无限循环的代码
ts
// 异常
function err(msg: string): never {
  // OK
  throw new Error(msg)
}

// 死循环
function loopForever(): never {
  // OK
  while (true) {}
}

never类型同nullundefined一样,也是任何类型的子类型,也可以赋值给任何类型。

除了 never 本身,没有类型可以赋值给 never,包括 any

ts
let ne: never
let nev: never
let an: any

ne = 123 // Error
ne = nev // OK
ne = an // Error
ne = (() => {
  throw new Error('异常')
})() // OK
ne = (() => {
  while (true) {}
})() // OK

never 作用:避免出现新增类型确没有具体实现

ts
type Foo = string | number

function controlFlowAnalysisWithNever(foo: Foo) {
  if (typeof foo === 'string') {
    // 这里 foo 被收窄为 string 类型
  } else if (typeof foo === 'number') {
    // 这里 foo 被收窄为 number 类型
  } else {
    // 利用never只能赋值为never这一特性
    const check: never = foo
  }
}

新增 boolean 后,没有具体的实现,会将 foo 赋值为 never,会报错

ts
type Foo = string | number | boolean

any

任何类型都可以被归为 any 类型。

  • any 相当于 js
  • 声明时,未指定其类型,默认为 any

一个普通类型,在赋值过程中改变类型是不被允许的,但是 any 可以

ts
let a: string = 'seven'
a = 7
// TS2322: Type 'number' is not assignable to type 'string'.

any 访问任何属性和方法

ts
let anyThing: any = 'hello'
console.log(anyThing.myName)
console.log(anyThing.myName.firstName)
let anyThing: any = 'Tom'
anyThing.setName('Jerry')
anyThing.setName('Jerry').sayHello()
anyThing.myName.setFirstName('Cat')

unknown ^3.0+^

any一样,所有类型都可以分配给unknown:

unkonwn 与 any 区别

  • any:任何类型都能赋值给 any,any 也能赋值给任何类型
  • unkown:任何类型都能赋值给 unkown,但它只能赋值给 unknown 和 any

总结:unknown 只能赋值给 any、unknown 。any 无限制。

不缩小类型,就无法对unknown类型执行任何操作。可以使用typeof类型断言等方式来缩小未知范围

ts
function getDogName() {
  let x: unknown
  return x
}
const dogName = getDogName()
// 直接使用
const upName = dogName.toLowerCase() // Error
// typeof
if (typeof dogName === 'string') {
  const upName = dogName.toLowerCase() // OK
}
// 类型断言
const upName = (dogName as string).toLowerCase() // OK

通常先声明 unknown,然后通过类型缩小来锁定具体类型

Number、String、Boolean、Symbol

Number、String、Boolean、Symbol 是相应原始类型的包装对象

原始类型兼容对应的对象类型,对象类型不兼容对应的原始类型。因此不要使用对象类型来注解值的类型。

ts
let num: number
let Num: Number
Num = num // ok
num = Num // ts(2322)报错

object、Object 和 {}

object:所有非原始类型

非原始类型能赋值给 object

ts
let lowerCaseObject: object
lowerCaseObject = 1 // ts(2322)
lowerCaseObject = 'a' // ts(2322)
lowerCaseObject = true // ts(2322)
lowerCaseObject = null // ts(2322)
lowerCaseObject = undefined // ts(2322)
lowerCaseObject = {} // ok

原始类型:stringbooleannumberbigintsymbolnullundefined

Object:所有拥有 toString、hasOwnProperty 方法的类型

所有原始类型、非原始类型都可以赋给 Object

ts
let upperCaseObject: Object
upperCaseObject = 1 // ok
upperCaseObject = 'a' // ok
upperCaseObject = true // ok
upperCaseObject = null // ts(2322)
upperCaseObject = undefined // ts(2322)
upperCaseObject = {} // ok

{}:原始类型和非原始类型的集合,等同 Object

严格模式下:undefined 和 null 不能赋值给 object、Object、{}

总结:Object 和 {} 可以互换,object 只表示非原始类型