编程TypeScript开发者

解释TypeScript中operator typeof在变量类型化中的角色和机制。如何使用它来推导变量或对象结构的类型,以及在什么情况下它比手动指定类型更可取?

用 Hintsage AI 助手通过面试

答案。

TypeScript支持typeof运算符,不仅在运行时(如JavaScript中),而且在编译时用于推导表达式的类型。这使得可以获取已声明变量、函数或对象结构的类型,从而使类型化更加灵活,减少类型重复和不同步的可能性。

问题的历史

最初,在JavaScript中,typeof运算符用于在运行时确定值的类型。TypeScript扩展了这个机制——现在在编译时,typeof创建一个对变量或函数结果的值类型的引用。这在处理复杂结构、配置文件以及在模块之间重复使用类型时非常有用。

问题

在手动声明类型时,容易犯错误:更改结构定义而忘记更新类型或接口声明,或者在对象之间复制类型时出错。这导致代码不同步和运行时错误。在使用typeof时,类型动态推导,并始终与当前数据结构相符。

解决方案

要声明一个与已有结构或常量相符的类型的变量,使用typeof运算符:

const config = { host: "localhost", port: 8080, }; let serverCfg: typeof config; // serverCfg的类型与config相同

用于类型化返回特定结构的函数:

function makeUser() { return { id: 1, name: "Alex" }; } type User = ReturnType<typeof makeUser>; // User: {id: number; name: string;}

关键特点:

  • typeof在TS中在编译时返回变量值或表达式结果的类型。
  • 可避免类型重复和不同步。
  • 常与额外的工具类型(如ReturnTypeParameters)以及keyof结合使用,以获取对象的键列表。

有陷阱的问题。

typeof运算符在TypeScript中在执行阶段执行吗?

不,类型的typeof仅在编译时工作,不会进入运行时代码,尽管JavaScript的typeof运算符在运行时存在。

typeof可以用来推导类属性的类型吗?

可以,但只有在属性已作为静态或具有初始值时,否则会出错。对于private/public protected——只能考虑公共属性/方法。

在'let x: typeof y;'和'let x = y;'之间有区别吗?

从类型的角度来看——在这两种情况下,编译器都会自动推导类型。然而,typeof可用于在没有初始化的情况下编写类型声明或进行更复杂的工具类型组合。

常见错误和反模式

  • 使用typeof进行常见的JS类型检查typeof x === 'string'——这是运行时,不是编译时类型。
  • 重复使用结构的值,而只需要它的形式(更好是将结构提取为单独的类型)。

生活中的示例

消极案例

在项目中将大型应用程序设置对象分别描述为类型和变量。在更改结构时忘记更新类型,这会导致API工作错误。

优点: 灵活的类型处理,可以通过type或interface重新定义类型

缺点: 类型和结构不同步的风险很大,维护性差

积极案例

使用typeof在声明新变量时获取对象结构的当前类型,并为API接口生成类型。

优点: 类型始终与值一致,错误概率低,自动补全良好

缺点: 如果对象非常复杂,最终的类型对于新手来说可能很难理解。