资讯详情

TypeScript typeof 类型运算符:从值到类型的桥梁与实战指南

📅 2026/9/29 3:26:18 | 华诺云谱 👁 阅读
TypeScript typeof 类型运算符:从值到类型的桥梁与实战指南
文档教程【免费下载链接】TypeScriptTypeScript 使用手册中文版翻译。http://www.typescriptlang.org项目地址https://gitcode.com/gh_mirrors/typ/TypeScript点击查看免费下载本文深入讲解 TypeScript 中typeof在类型上下文中的用法如何用typeof引用变量或属性的类型、如何与ReturnType、keyof等类型运算符组合实现常见模式以及它在标识符使用上的限制与规避方法。读完本文你将掌握用已有值推导类型的核心技巧能够在函数返回值提取、枚举键类型、数组元素类型提取等真实场景中写出类型安全且可维护的代码。本文以本仓库 zh/handbook-v2/type-manipulation/typeof-type-operator.md 为主线并结合仓库中 zh/handbook-v2/type-manipulation/ 系列文档与 zh/reference/utility-types.md 进行佐证扩充。一、从 JavaScript 的typeof说起表达式上下文与类型上下文typeof并不是 TypeScript 的新发明JavaScript 本身就有它。在表达式expression上下文中typeof返回的是一个字符串描述操作数的运行时类型// 输出 string console.log(typeof Hello world);TypeScript 为typeof增加了全新的用途——你可以在类型type上下文中使用它来引用某个变量或属性的类型let s hello; let n: typeof s; // ^?这里n的类型被声明为typeof s也就是s的类型string。换句话说在类型位置上typeof的作用是把值映射到它的类型它连接了 TypeScript 中两个彼此区分的世界值世界value space与类型世界type space。对于基本类型如string、number来说直接写typeof s略显多余——毕竟你可以直接写let n: string。但在 TypeScript 中一个变量的类型可能由复杂的推断产生对象字面量、函数返回、类实例等此时typeof就成了唯一能够反查出该类型的手段。这一点正是本仓库 zh/handbook-v2/type-manipulation/_creating-types-from-types.md 中所说的用我们已有的值表达类型。二、值世界与类型世界为什么需要typeof在深入组合用法之前必须先厘清一个核心观念值value和类型type不是相同的东西。变量f是一个值它存在于运行时ReturnType需要的是类型即描述f的那个类型。直接对函数名使用ReturnType会得到 2749 号错误// errors: 2749 function f() { return { x: 10, y: 3 }; } type P ReturnTypef;TypeScript 给出的错误信息正是f指代一个值但在此处被用作类型。而一旦我们用typeof把值f转换成它的类型一切就顺理成章了function f() { return { x: 10, y: 3 }; } type P ReturnTypetypeof f; // ^?此时P被推断为{ x: number; y: number }。这个模式在仓库中反复出现例如 zh/reference/utility-types.md 中对ReturnTypeType的示例type T4 ReturnTypetypeof f1; // { a: number, b: string }以及InstanceType的示例type T0 InstanceTypetypeof C; // C——利用typeof捕获类的构造函数类型再进一步得到实例类型。由此可见typeof是这些实用工具类型与真实代码之间的适配器。三、与ReturnType组合提取函数的返回值类型回到文档中的经典案例。ReturnTypeT是 TypeScript 预定义的一个实用工具类型它接受一个函数类型作为参数并生成其返回值类型type Predicate (x: unknown) boolean; type K ReturnTypePredicate; // ^?这里K是boolean。但注意Predicate本身就是一个类型函数类型所以可以直接传给ReturnType。而当你面对的是一个真实的函数值时就必须先typeoffunction f() { return { x: 10, y: 3 }; } type P ReturnTypetypeof f; // ^?这是实际项目中最常见的组合之一ReturnTypetypeof someFunction让你无需重复声明返回值类型。当f的返回值结构发生变化时P会自动跟随避免了手写类型与实现之间的漂移drift。这正是以值推导类型在维护性上的核心价值。值得补充的是ReturnType对重载函数的行为值得注意当从具有多个调用签名的类型如重载函数的类型进行推断时将从最后一个签名进行推断。本仓库 zh/handbook-v2/type-manipulation/conditional-types.md 中给出了这一行为的具体验证declare function stringOrNum(x: string): number; declare function stringOrNum(x: number): string; declare function stringOrNum(x: string | number): string | number; type T1 ReturnTypetypeof stringOrNum; // ^? 推断为 string | number最后一个签名这也解释了为何ReturnType的实现本质是一个条件类型type ReturnTypeT T extends (...args: any[]) infer R ? R : any;见 zh/handbook-v2/type-manipulation/conditional-types.md 中关于infer的讲解。用typeof拿到函数类型后ReturnType内部通过infer R提取返回值——两层机制环环相扣。四、typeof的限制只能在标识符或其属性上使用TypeScript有意限制了你可以在其上使用typeof的表达式类型。具体来说只有在标识符即变量名或其属性上使用typeof才是合法的。这一限制是为了避免你认为正在执行、但实际上没有执行的代码带来的混淆陷阱。请看下面的错误示例// errors: 1005 declare const msgbox: (prompt: string) boolean; // type msgbox any; // ---cut--- // 本意是使用 ReturnTypetypeof msgbox let shouldContinue: typeof msgbox(你是否确定要继续);这里本意是写ReturnTypetypeof msgbox但由于手误把括号写到了typeof后面变成了typeof msgbox(...)——在类型位置上对一次函数调用表达式使用typeof。这会触发 1005 号语法错误应为标识符或限定名称TypeScript 以此提醒你类型上下文中的typeof只能作用于名字不能作用于任意表达式。这与 JavaScript 运行时typeof的行为形成鲜明对比JS 的typeof可以对任意表达式求值typeof msgbox(...)会真的调用函数并返回boolean但类型系统是静态的、不会执行代码因此类型上下文中的typeof只能引用那些可以被静态解析的名字。补充一个关联知识点这一限制同样适用于.d.ts环境声明。本仓库 zh/breaking-changes/typescript-2.6.md 中提到在声明文件和环境模块中任何不是标识符或限定名称的表达式现在都会被标记为错误因为typeof之类的意图不明确。五、与keyof组合枚举的键类型提取typeof与keyof的组合是枚举场景下的经典技巧。keyof作用于对象类型生成其键的字面量联合类型参见 zh/handbook-v2/type-manipulation/keyof-type-operator.md。但枚举是一个运行时真实存在的对象keyof直接作用于枚举标识符时行为不同——正确的做法是keyof typeof Enumenum LogLevel { ERROR, WARN, INFO, DEBUG, } /** * 等同于 * type LogLevelStrings ERROR | WARN | INFO | DEBUG; */ type LogLevelStrings keyof typeof LogLevel; function printImportant(key: LogLevelStrings, message: string) { const num LogLevel[key]; if (num LogLevel.WARN) { console.log(Log level key is: , key); console.log(Log level value is: , num); } }这里typeof LogLevel先把枚举值对象映射为它的对象类型包含所有成员keyof再取出这些成员的键。整个过程分解来看就是[枚举名]值→typeof→ 对象类型 →keyof→ 字符串键联合。该示例完整出现在 zh/handbook/enums.md 的编译时的枚举一节中。keyof typeof组合还能用于普通对象常量。结合 zh/handbook-v2/type-manipulation/keyof-type-operator.md 中keyof对索引签名的行为{ [k: string]: boolean }的keyof是string | number因为 JavaScript 对象的键总是被强制转换为字符串你可以对配置对象、常量映射等写出精确的键联合类型。六、与索引访问类型组合捕获数组字面量的元素类型typeof的另一高频组合是与索引访问类型indexed access type一起使用。索引访问类型让你用Type[a]语法在另一个类型上查找特定属性参见 zh/handbook-v2/type-manipulation/indexed-access-types.md。当你有一个数组/对象字面量时typeof恰好能捕获它的精确类型const MyArray [ { name: Alice, age: 15 }, { name: Bob, age: 23 }, { name: Eve, age: 38 }, ]; type Person typeof MyArray[number]; // ^? type Age typeof MyArray[number][age]; // ^? // 或者 type Age2 Person[age]; // ^?这里的要点是typeof MyArray得到数组字面量类型{ name: string; age: number }[][number]索引访问取出其元素类型{ name: string; age: number }再叠加[age]可以继续下钻到number。需要注意的是在进行索引时只能使用类型不能使用const变量作为索引键会触发 2538 号错误但可以使用类型别名完成等价重构参见 zh/handbook-v2/type-manipulation/indexed-access-types.md。七、与映射类型、条件类型协同构建可维护的类型工厂typeof的更大威力在于与类型系统中的管道协作。本仓库 zh/handbook-v2/type-manipulation/_creating-types-from-types.md 明确列出了六种类型操作符泛型、keyof、typeof、索引访问类型、条件类型、映射类型、模板字面量类型。typeof在其中扮演的角色是把值世界的信息注入类型世界进而喂给其他操作符。典型组合是typeof 映射类型mapped type。映射类型用[Property in keyof Type]遍历键并转换属性类型参见 zh/handbook-v2/type-manipulation/mapped-types.mdconst config { darkMode: () true, retries: 3, }; // 把所有属性值转换为 boolean示意 type FlagsT { [K in keyof T]: boolean; }; type ConfigFlags Flagstypeof config; // ^? { darkMode: boolean; retries: boolean }同样typeof也可以与条件类型配合。条件类型允许在extends判断的 true 分支中通过infer提取类型参见 zh/handbook-v2/type-manipulation/conditional-types.md。例如定义一个提取任意函数的参数类型的辅助工具并配合typeof应用于真实函数type MyParametersT extends (...args: any) any T extends (...args: infer P) any ? P : never; function greet(name: string, age: number) { return Hello ${name}, age ${age}; } type GreetArgs MyParameterstypeof greet; // ^? [name: string, age: number]从这里可以看出TypeScript 内置的ParametersType、ConstructorParametersType、ReturnTypeType、InstanceTypeType等实用工具类型zh/reference/utility-types.md 中统称为全局可见的类型都依赖同样的条件类型 infer机制而typeof正是把这些工具从类型签名应用到真实代码的关键桥梁。八、实践清单与易错点小结最后汇总typeof类型运算符在实战中的要点与易错点场景写法说明获取变量/属性的类型typeof s基本类型场景略显冗余复杂推断类型场景价值显著提取函数返回值ReturnTypetypeof f避免手写返回值类型与实现漂移对重载函数取最后一个签名提取函数参数Parameterstypeof f内置工具类型同样以typeof为入口提取类实例类型InstanceTypetypeof C先typeof得到构造函数类型枚举键类型keyof typeof LogLevel对枚举、常量对象取字符串键联合数组元素类型typeof MyArray[number]与索引访问类型组合捕获字面量元素类型与映射/条件类型组合Flagstypeof config等把值世界的信息注入类型工厂易错点不要对函数名直接用ReturnTypef——f是值不是类型触发 2749 号错误必须写ReturnTypetypeof f类型上下文中的typeof不能作用于任意表达式——如typeof msgbox(...)触发 1005 号语法错误只能作用于标识符或其属性typeof obj.prop是合法的限定名称用法索引访问时不能用const变量作键——要用类型别名如type key age替代分清两个typeof——JavaScript 的typeof在表达式上下文返回运行时类型字符串TypeScript 的typeof在类型上下文返回静态类型二者语法相同但语义与使用位置完全不同。延伸阅读zh/handbook-v2/type-manipulation/_creating-types-from-types.md——用现有类型/值创建新类型的总览zh/handbook-v2/type-manipulation/keyof-type-operator.md——keyof类型运算符详解zh/handbook-v2/type-manipulation/indexed-access-types.md——索引访问类型详解zh/handbook-v2/type-manipulation/conditional-types.md——条件类型与infer提取zh/handbook-v2/type-manipulation/mapped-types.md——映射类型详解zh/reference/utility-types.md——内置实用工具类型含ReturnType、InstanceType完整示例zh/handbook/enums.md——keyof typeof提取枚举键类型的实战用例赞分享文档教程【免费下载链接】TypeScriptTypeScript 使用手册中文版翻译。http://www.typescriptlang.org项目地址https://gitcode.com/gh_mirrors/typ/TypeScript点击查看免费下载相关推荐TypeScript 中从值推导类型类型推断、字面量收窄与 typeof 提取实践TypeScript 中从值推导类型类型推断、字面量收窄与 typeof 提取实践 导读 type from value Type à partir du文档教程从值到类型TypeScript 类型推断Type from Value机制与实战指南从值到类型TypeScript 类型推断Type from Value机制与实战指南 TypeScript 最核心的体验之一就是从值推导类型——编译文档教程Flow typeof 类型操作符实战从 DEFAULT_SETTINGS 值派生函数签名并防止类型漂移Flow typeof 类型操作符实战从 DEFAULT_SETTINGS 值派生函数签名并防止类型漂移 本篇指南围绕仓库中 evals/evals/02_u开发工具静态分析代码质量上一篇25fps 和 800×600 困在 16:9 屏幕中央D2DX 宽屏补丁一个 DLL 让暗黑破坏神2 跑上高帧率下一篇KMS激活完整指南一条命令搞定 Windows 11 与 Office 2024 激活创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑