TypeScript 类型断言、类型推论

类型断言

类型断言是一种 TypeScript 特性,用于告诉编译器将一个值视为特定的类型,即使编译器本身的类型推断可能不同。

类型断言并不会改变变量的实际运行时类型,而是在编译阶段告知TypeScript编译器开发者期望该表达式具有某种类型。

注意:类型断言 不是 类型转换,因为转换通常意味着某种运行时的支持。但类型断言纯粹是一个编译时语法,只是在编译阶段起作用,不进行特殊的数据检查和解构,它没有运行时的影响。同时,它也是一种为编译器提供关于如何分析代码的方法

语法格式:

  1. <类型>值
  2. 值 as 类型

类型断言主要用于以下情况:

  1. 当 TypeScript 的类型推断不够精确,而开发者明确知道变量的实际类型时。
  2. 当需要访问特定类型的属性或方法,但 TypeScript 由于自身的类型限制不允许直接访问时。
let someValue: any = "Hello, TypeScript!";

// 方式一:<类型>值
let length1: number = (<string>someValue).length;

// 方式二:值 as 类型
let length2: number = (someValue as string).length;

当你在TypeScript里使用JSX时,只有 as 语法断言是被允许的。

类型推断

在 TypeScript 中,类型推论允许 TypeScript 在某些情况下根据变量的初始化值自动推断出变量的类型。

类型推断发生在初始化变量和成员,设置默认参数值和决定函数返回值时。

  1. 变量初始化时的类型推论
    当声明一个变量并同时为其赋值时,TypeScript 会根据赋值的值来推断变量的类型。

示例:

let num = 5;  // TypeScript 会推断 num 的类型为 number
let isTrue = true;  // TypeScript 会推断 isTrue 的类型为 boolean
let arr = [1, 2, 3];  // TypeScript 会推断 arr 的类型为 number[]

let str = "Hello";  // TypeScript 会推断 str 的类型为 string
str = "hi"; // 合法,str 的类型为 string
str = 10;  // Error: 不能将类型“number”分配给类型“string”。

当需要从几个表达式中推断类型时候,会使用这些表达式的类型来推断出一个最合适的通用类型。

let arr = [0, 1, null];

数组 arr 中的元素包含了数字 01 ,以及 null ,所以数组元素的类型被推断为 numbernull 的联合类型,整个数组的类型就是 (number | null)[]

  1. 函数返回值的类型推论
    如果函数的返回值是通过计算得出的,并且没有显式指定返回值类型,TypeScript 会根据返回的表达式来推断函数的返回值类型。

示例:

function sum(a: number, b: number) {
  return a + b;  // TypeScript 会推断该函数的返回值类型为 number
}
  1. 对象属性的类型推论
    在对象初始化时,TypeScript 也会对对象属性进行类型推论。

示例:

// TypeScript 会推断 person 的类型为具有 name: string 和 age: number 属性的对象类型
let person = {
  name: "John",
  age: 30
}; 

// 对象字面量只能指定已知属性,并且“firstName”不在类型“{ name: string; age: number; }”中。
person = {
  firstName: "John",
  lastName: "Bob"
}

在这里插入图片描述

由于最终的通用类型取自候选类型,有些时候 候选类型 共享 相同的通用类型,但是却没有一个类型能做为所有候选类型的类型。
没有通用类型:

let zoo = [new Rhino(), new Elephant(), new Snake()];

在这种情况下,TypeScript 编译器 会根据数组中元素的实际类型来推断数组的类型。
在数组中, RhinoElephantSnake 是自定义的类,它们之间没有找到最佳通用类型,类型推断的结果为联合数组类型:(Rhino | Elephant | Snake)[]

如果想要TypeScript编译器 推断zoo的类型为Animal[],但是这个数组里没有对象是Animal类型的,因此不能推断出这个结果。
当候选类型不能作为最佳通用类型使用的时候,需要明确的指出类型:

let zoo: Animal[] = [new Rhino(), new Elephant(), new Snake()];

既然TypeScript 编译器会自动判断变量的类型,那为什么还要在编写代码时明确类型声明呢?

JavaScript的变量没有类型,在运行时明确变量的值的类型。
在单纯的为变量a赋值时,a是什么类型都影响不大:a = 10a = "hello"a = true
假如a作为某个函数的参数,需要传递到函数中使用呢?

function sum(a, b) {
  return a + b;
}
console.log( sum(10, 15) );  // 25
console.log( sum("10", 15) );  // "1015"

假如要将计算结果进行展示或在别的函数里继续使用,会导致更多错误。
sum(10, 15)sum("10", 15)的计算结果相差很大,但是代码不会报错,那排查问题就会特别困难。
因此,明确声明该参数的类型可以防止意外传递错误类型的值,并且在阅读函数定义时就能清楚了解输入的预期。

function sum(a:number, b:number) {
  return a + b;
}
console.log( sum(10, 15) );  // 25
console.log( sum("10", 15) );  // Error: 类型“string”的参数不能赋给类型“number”的参数。

明确指出变量类型有以下好处:

  1. 增强代码的自解释性
    • 明确的类型声明使其他开发者在阅读代码时能更快速、清晰地理解变量的预期用途和可能的值。
  2. 提高代码的可维护性
    • 当代码规模较大或经过多人协作开发时,显式的类型有助于确保代码的一致性和规范性。
    • 未来进行代码修改和扩展时,清晰的类型信息可以降低出错的风险。
  3. 提前发现错误,增强类型安全性
    • 显式声明类型,编译器能在编译阶段检测到更多潜在的类型不匹配错误,减少潜在的运行时错误。
  4. 更好的开发工具支持
    • 开发工具可以基于明确的类型提供更准确和有用的代码提示、自动完成和重构功能。
  5. 文档化代码
    • 类型声明相当于为代码添加了一种内置的文档,方便后续开发者理解。

类型断言、类型推论的区别

类型断言

  • 手动干预:是开发者手动告诉编译器将某个值视为特定的类型,即使编译器本身的推断可能不同。
  • 显式语法:通过特定的语法 <类型>值值 as 类型 来实现。
  • 可能存在风险:如果断言不正确,可能在运行时导致错误,因为编译器在编译阶段不会深入检查断言的正确性。

类型推论(Type Inference):

  • 自动进行:TypeScript 编译器根据变量的初始化值或函数的返回值等上下文信息,自动推断出变量或返回值的类型。
  • 无需显式操作:开发者不需要进行任何特殊的语法或操作来触发类型推论,它是在编译时由编译器自动完成的。
  • 基于值:类型的推断是基于所赋的值或计算得出的结果。
  • 17
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值