ts类型断言与类型推断

类型断言

在 TypeScript 中,类型断言(Type Assertion)是一种告诉编译器"我知道这个值的类型是什么"的机制。这种机制主要有两种形式:尖括号语法(Angle Bracket Syntax)和 as 语法。

尖括号语法

typescript 复制代码
let value: any = "This is a string";
let strLength: number = (<string>value).length;

// 或者
let alternativeWay: number = (value as string).length;

在上面的例子中,value 被声明为 any 类型,然后通过尖括号语法或 as 语法将其断言为 string 类型,以便获取其 length 属性。这样,开发者告诉 TypeScript 编译器:"我确信 value 是一个字符串。"

as语法

ini 复制代码
let value: any = "This is a string";
let strLength: number = (value as string).length;

在这个例子中,我们使用了 as 语法来进行类型断言,效果和尖括号语法是一样的。


举个例子,现在有这样一个函数,

kotlin 复制代码
const getLength = target => {
  if (target.length) {
    return target.length;
  } else {
    return target.toString().length;
  }
};

这是一个 JavaScript 函数,用于获取目标对象的长度。函数采用一个参数 target,然后通过检查目标对象的 .length 属性是否存在来确定其类型。

如果目标对象有 .length 属性,函数直接返回该属性的值,假定该对象是一个具有长度属性的对象(比如数组、字符串等)。

如果目标对象没有 .length 属性,函数假设该对象可能是一个不具有 .length 属性的对象,然后通过将其转换为字符串并获取字符串的长度来返回对象的长度。

现在考虑这个函数的TypeScript实现,如果按下述方式编写

typescript 复制代码
const getLength = (target: string | number): number => {
  if (target.length) { // 类型"string | number"上不存在属性"length"。类型"number"上不存在属性"length"。
    return target.length; // error 报错信息看下方
  } else {
    return target.toString().length;
  }
};

函数的参数 target 被定义为 string | number,表示它可以是字符串或数字类型。然而,在 TypeScript 中,对于联合类型,你不能直接访问其类型的属性或方法,因为并非所有可能的类型都具有相同的属性。

在这个函数中,TypeScript 报错是因为它无法确定 target 到底是一个字符串还是一个数字,而它尝试访问 .length 属性,这个属性在数字类型上是不存在的。

因此可以考虑采用类型断言

typescript 复制代码
const getStrLength = (target: string | number): number => {
  if ((<string>target).length) { // 这种形式在JSX代码中不可以使用,而且也是TSLint不建议的写法
    return (target as string).length; // 这种形式是没有任何问题的写法,所以建议大家始终使用这种形式
  } else {
    return target.toString().length;
  }
};

我们希望对 target 进行判断并访问其 length 属性,但由于 target 是一个联合类型 string | number,TypeScript 不确定它的具体类型。因此,我们在进行判断之前需要告诉 TypeScript 我们认为 target 是一个字符串类型。

在这个函数中,使用了类型断言来告诉 TypeScript,你确定 target 是一个字符串。有两种类型断言的写法:

(<string>target).length:这是一种旧式的写法,不推荐在 JSX 代码中使用,而且 TSLint 也不建议这种写法。

(target as string).length:这是一种更现代、更安全的写法,也是推荐使用的方式。

所以,建议使用第二种写法,即 (target as string).length。这样可以避免潜在的问题,并且在 JSX 代码中也是可用的。

类型推断

多类型联合

ini 复制代码
let arr = [1, "a"];
arr = ["b", 2, false]; // error 不能将类型"false"分配给类型"string | number"

当我们定义一个数组或元组时,TypeScript 会对数组中元素的类型进行合并形成联合类型。这就意味着,数组或元组的元素可以是多个不同类型中的任意一种。

在给定的例子中,arr 的元素类型被推断为 string | number,这表示数组中的元素可以是 string 类型,也可以是 number 类型,但不允许其他类型,例如 boolean。所以,当尝试将 false 赋值给 arr 时,TypeScript 报错,因为 false 的类型是 boolean,不属于联合类型 string | number。

ini 复制代码
let value = Math.random() * 10 > 5 ? 'abc' : 123
value = false // error 不能将类型"false"分配给类型"string | number"

value 的类型被推断为联合类型 string | number。这是因为它的赋值取决于三元操作符的条件。如果条件为真,value 是字符串类型 'abc',如果条件为假,value 是数值类型 123。

当你尝试将 false 赋值给 value 时,TypeScript 报错。这是因为 false 的类型不属于 string | number 联合类型,所以 TypeScript 认为这是一个类型不匹配的错误。

这种方式使得 TypeScript 可以在编译阶段捕获到潜在的类型错误,增加了代码的类型安全性。

上下文类型

在 TypeScript 中,上下文类型是一种类型推断的机制,它是根据变量声明的上下文来推断该变量的类型。上下文类型通常发生在赋值语句的左侧,即当你给一个变量赋值时,TypeScript 根据变量被赋值的上下文来推断变量的类型。

javascript 复制代码
window.onmousedown = function(mouseEvent) {
  console.log(mouseEvent.a); // error 类型"MouseEvent"上不存在属性"a"
};

window.onmousedown 被赋值为一个函数,而该函数有一个参数 mouseEvent。TypeScript 尝试根据赋值语句的上下文来推断 mouseEvent 的类型。

上下文: window.onmousedown 是一个事件处理函数,因此 TypeScript 推断 mouseEvent 应该是鼠标事件对象 (MouseEvent)。

推断的类型: TypeScript 推断 mouseEvent 的类型为 MouseEvent,因为它是 onmousedown 事件处理函数的参数。

类型检查: 在你尝试访问 mouseEvent.a 时,TypeScript 进行了类型检查。由于 MouseEvent 类型并没有名为 a 的属性,所以 TypeScript 报错,指出在 MouseEvent 上不存在属性 a。

总体而言,上下文类型推断是 TypeScript 在缺少显式类型注释时,通过根据表达式的上下文(在这里是事件处理函数)来推断变量类型的一种方式。

相关推荐
天涯学馆6 小时前
Deno与Secure TypeScript:安全的后端开发
前端·typescript·deno
applebomb9 小时前
【2024】uniapp 接入声网音频RTC【H5+Android】Unibest模板下Vue3+Typescript
typescript·uniapp·rtc·声网·unibest·agora
读心悦20 小时前
TS 中类型的继承
typescript
读心悦21 小时前
在 TS 的 class 中,如何防止外部实例化
typescript
Small-K1 天前
前端框架中@路径别名原理和配置
前端·webpack·typescript·前端框架·vite
宏辉1 天前
【TypeScript】异步编程
前端·javascript·typescript
LJ小番茄2 天前
TS(type,属性修饰符,抽象类,interface)一次性全部总结
前端·javascript·vue.js·typescript
It'sMyGo3 天前
Javascript数组研究03_手写实现_fill_filter_find_findIndex_findLast_findLastIndex
前端·javascript·typescript
bobostudio19953 天前
TypeScript 算法手册【快速排序】
前端·javascript·算法·typescript
垂钓的小鱼13 天前
尚硅谷vue3+TypeScript笔记大全
javascript·typescript·vue