您现在的位置是:首页 >技术交流 >typescript 中的 断言网站首页技术交流

typescript 中的 断言

哇吖吖 2024-07-17 08:12:27
简介typescript 中的 断言

? 类型断言

as<>都可以用来类型推断,但是尖括号格式会与 reactJSX 产生语法冲突,因此我们更推荐使用 as 语法。

 ? as

有些情况下 ts 并不能正确或者准确得推断类型,这个时候可能产生不必要的警告或者报错

const person = {};

person.name = 'randy'; // Error: 'name' 属性不存在于 ‘{}’
person.age = 20; // Error: 'age' 属性不存在于 ‘{}’

解决方法:添加类型断言

interface Person {
  name: string;
  age: number;
}

const person = {} as Person;

person.name = 'randy';
person.age = 20;

 ? <>

如果代码中使用 document.getElementByIdts 只知道这将返回某种 HTMLElement,但我们确定页面将始终具有具有给定 ID 的 HTMLCanvasElement

  • 通过上述的as断言
const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;
  • 通过<>断言
const myCanvas = <HTMLCanvasElement>document.getElementById("main_canvas");

? 双重断言

const a = expr as any as T;
虽然类型断言是有强制性的,但并不是万能的,因为一些情况下也会失效:

const x = "hello" as number;
// Conversion of type 'string' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.

先把类型断言为 any 再接着断言为你想断言的类型就能实现双重断言

const x = "hello" as any as number;

? 非空断言

在上下文中当类型检查器无法断定类型时,一个新的后缀表达式操作符 !可以用于断言操作对象是非 null 和非undefined
类型。具体而言,x! 将从 x 值域中排除 nullundefined

先来看个示例:

function sayHello(name: string | undefined) {
  let sname: string = name; // Error
}

对于以上代码,TypeScript 编译器会提示一下错误信息:

Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.

要解决上述问题,我们可以简单加个条件判断:

function sayHello(name: string | undefined) {
  let sname: string;
  if (name) {
    sname = name;
  }
}

使用这种方案,问题是解决了。但有没有更简单的方式呢?答案是有的,就是使用 TypeScript 2.0 提供的非空断言操作符:

function sayHello(name: string | undefined) {
  let sname: string = name!;
}

? 确定赋值断言

使用场景:定义了变量, 没有赋值, 就使用,则会报错

 ? Example1

let num: number;
console.log(num); // error Variable 'num' is used before being assigned.
let num!: number;
console.log(num); // undefined

 ? Example2

let x: number;
initialize();

// Variable 'x' is used before being assigned.
console.log(x); // Error

function initialize() {
  x = 10;
}
let x!: number;
initialize();

// Variable 'x' is used before being assigned.
console.log(x); // Error

function initialize() {
  x = 10;
}

? 类型守卫

类型守卫说白了就是缩小类型的范围,常用的有

  • 类型判断:typeof
  • 实例判断:instanceof
  • 属性判断:in
  • 字面量相等判断:==, ===, !=, !==

 ? 类型判断:typeof

function test(input: string | number) {
  if (typeof input == 'string') {
    // 这里 input 的类型「收紧」为 string
  } else {
    // 这里 input 的类型「收紧」为 number
  }
}

 ? 实例判断:instanceof

class Foo {}
class Bar {}

function test(input: Foo | Bar) {
  if (input instanceof Foo) {
    // 这里 input 的类型「收紧」为 Foo
  } else {
    // 这里 input 的类型「收紧」为 Bar
  }
}

 ? 属性判断:in

interface Foo {
  foo: string;
}

interface Bar {
  bar: string;
}

function test(input: Foo | Bar) {
  if ('foo' in input) {
    // 这里 input 的类型「收紧」为 Foo
  } else {
    // 这里 input 的类型「收紧」为 Bar
  }
}

 ? 字面量相等判断:==, ===, !=, !==

type Foo = 'foo' | 'bar' | 'unknown';

function test(input: Foo) {
  if (input != 'unknown') {
    // 这里 input 的类型「收紧」为 'foo' | 'bar'
  } else {
    // 这里 input 的类型「收紧」为 'unknown'
  }
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。