Skip to content

断言 ​

as 断言 ​

as 断言的意思就是用户断定这是什么类型,不使用系统推断的类型。

下例中TS会根据函数推断变量f的类型是string|number

ts
function test(arg: number){
  return arg?'test': 2023
}

let f = test(1) // let f: string|number

我们可以由开发者来断定这就是字符串,这就是断言。

ts
function test(arg: number) {
  return arg ? 'test': 2023
}

let f = test(1) as string // let f: string

也可以使用下面的断言语法

ts
function test(arg: number) {
  return arg ? 'test': 2023
}

let f = <string>f(1) // let f: string

const 断言 ​

let & const ​

  • const 保证该字面量的严格类型
  • let 为能用类型比如字符串类型
ts
const t = 'test' // const t: 'test'
let x = 'test' // let x: string

const ​

const断言告诉编译器为表达式推断出它能推断出它能推断出的最窄或最特定的类型,而不是宽泛的类型

  • 字符串、布尔类型转换为具体值
  • 对象转换为只读属性
  • 数组转换成为只读元组

下面限定user类型为'test'

ts
let user = '测试' as const
user = 'test' // error

对象转换为只读属性

ts
let user = {name: '测试'} as const
user.name = 'test' // error 因为是只读属性,所以不允许设置值

当为对象值为变量时,as const后具体值类型为这个变量的类型

ts
let a = 'test'
let b = 1 as const

let f = {
  name: a,
  arg : b
} as const

数组赋值 ​

变量f得到的类型是数组的类型string|number,所以只要值是这两个类型都可以

ts
let a = 'test'
let b = 1

let arr = [a, b] // let arr: (string|number)[]
let f = arr[1] // let f: string|number
f = '测试' // ok 因为类型是 string|number

使用const之后得到值的具体类型,而不是数组的类型

ts
let a = 'test'
let b = 1

let arr = [a, b] as const // let arr: readonly [string, number]
let f = arr[1] // let f: number
f = '测试' // error 不能将类型“string”分配给类型“number”

也可以使用以下语法

ts
let a = 'test'
let b = 1

let arr = <const>[a, b] // let arr: readonly [string, number]
let f = arr[1] // let f: number
f = 199

解构 ​

下面解构得到的变量类型不是具体类型,而是数组类型,比如变量y的类型是string | (()=>void)这在写项目时是不安全的,因为可以将y随时修改为字符串,同时也不会有友好的代码提示

ts
function test(){
  let a = '测试'
  let b = (x: number, y: number): number => x + y
  return [a, b]
}

let [n, m] = test() // 变量 m 的类型为 string | (() => void)

m(1, 6) // error 因为类型可能是字符串,所以不允许调用

可以断言m为函数然后调用

ts
function test(){
  let a = '测试'
  let b = (x: number, y: number): number => x + y
  return [a, b]
}

let [n, m] = test() 
console.log((m as Function)(1,3))

// 使用下面类型声明也可以
console.log((m as (x: number, y: number) => number)(1,2))

可以在调用时对返回值断言类型

ts
function test() {
  let a = '测试'
  let b = (x: number, y: number): number => x + y
  return [a, b]
}

let [n, m] = test() as [string, (x: number, y: number) => number]
console.log(m(1, 2))

也可以在函数体内声明返回类型

ts
function test() {
    let a = '测试'
    let b = (x: number, y: number): number => x + y
    return [a, b] as [typeof a, typeof b]
}

let [n, m] = test()
console.log(m(1, 2))

使用 as const 就可以很高效的解决上面的问题,可以得到具体的类型,来得到更安全的代码,同时会有更好的代码提示

ts
function test() {
  let a = '测试'
  let b = ():void => {}
  return [a, b] as const
}

const [x, y] = test() // 变量 y 的类型为 ()=>void

因为const是取值的类型,下面代码虽然不报错,但此时b的类型已经是字符串或函数,所以像下面一样在函数调用时as const没有意义。

ts
function test() {
  let a = '测试'
  let b = (x: number, y: number): number => x + y
  return [a, b]
}

const [n, m] = [...test()] as const // 没有意义

也可以使用泛型来处理

ts
function test() {
    let a = '测试'
    let b = (x: number, y: number): number => x + y
    return test2(a, b)
}

function test2<T extends any[]>(...args: T): T {
    return args
}

const [n, m] = test();


console.log(m(1, 3))

null/undefined ​

默认情况下null与undefined可以赋值给其他类型

ts
let test: string = '测试'
test = null // 不能将类型“null”分配给类型“string”。
test = undefined // 不能将类型“undefined”分配给类型“string”。

当我们修改 tsconfig.json 配置文件的 strictNullChecks 字段为 true(默认即为 true) 时,则不能将 null、undefined 赋值给其他类型

json
"strictNullChecks": true

除非向下面一样明确指定类型

ts
let test: string | null | undefined = '测试'
test = null
test = undefined

非空断言 ​

下面的示例获取的值可能为HTMLDivElement或null,所以直接分配类型HTMLDivElement将报错。

下例操作需要开启tsconfig.json的配置项strictNullChecks字段为true

ts
const el: HTMLDivElement = document.querySelector('#test') //error 不能将类型“HTMLDivElement | null”分配给类型“HTMLDivElement”。
console.log(el.id)

可以使用as断言类型

ts
const el: HTMLDivElement = document.querySelector('.test') as HTMLDivElement // ok
console.log(el.id)

在值后面使用!来声明值非null

ts
const el: HTMLDivElement = document.querySelector('.test')! // ok
console.log(el.id)