Sunday面试指南

TypeScript 结构化类型是什么?为什么对象多一个字段,有时能赋值、有时却报错?

下面是一段教学用的模拟面试。

🧑‍💻 面试官:TypeScript 按什么判断两个对象类型兼容?

🙋‍♂️ 我:主要看对象有哪些成员,以及成员类型是否满足要求。

🧑‍💻 面试官:一个只要求 name 的类型,可以接收多一个 age 的变量吗?

🙋‍♂️ 我:通常可以,目标需要的结构已经满足了。

🧑‍💻 面试官:那直接把 { name, age } 字面量赋给它,为什么又报额外属性错误?是不是类型系统前后矛盾?

「满足目标结构」和「检查新写对象的可疑字段」是两道检查,不是两套相反的类型规则。

面试速答(60 秒版)

TypeScript 主要采用结构化类型。判断一个值能否交给目标类型,重点是它有没有目标要求的成员,类型是否兼容,而不是有没有显式声明同一个类型名字。

但新鲜的对象字面量会进行额外属性检查,帮助发现拼错字段等问题。因此,多一个字段的变量可能可以赋值,同样字段直接写成字面量却可能报错。

这不表示通过变量就能让错误字段变正确。缺少必需字段、成员类型错误,仍然可能失败;编译通过也不会把额外字段从运行时对象里删掉。处理接口输入还要做运行时校验,不能把结构化兼容当成精确对象验证。

类型看结构,运行时不删字段

图:类型看结构,运行时不删字段。

知识点详解:展示函数只需要 name,为什么用户对象可以传进去?

类型描述需要的能力,不必描述对象的全部

假设咱们有一个展示姓名的函数,只读取 name。用户对象还有 age、avatar 等字段,但这不妨碍函数读取姓名。

结构化类型就在检查这件事:目标要求 name 是字符串,来源有没有一个满足要求的 name?有,就满足这一部分契约。来源叫什么类型,不是主要判断依据。兼容性文档说明了这种基于成员的比较。

因此,两个分别声明的类型,只要相关结构相容,也可能互相赋值。反过来,类型名字很像,也不代表成员类型一定相容。类的 private/protected 等成员还会增加限制,不能说所有类型都只比较公开字段数量。

新写一个对象时,编译器还会多检查一步

相同字段,检查入口不同

图:相同字段,检查入口不同。

TypeScript

type Named = { name: string };
const user = { name: '小周', age: 22 };
const first: Named = user; // 目标结构满足
// @ts-expect-error 新鲜字面量的额外属性检查
const second: Named = { name: '小周', age: 22 };
console.log(first.name);

同学看到这里,容易把结论记成「赋给变量就能绕过所有检查」。不是。把 name 改成数字,或者干脆漏掉 name,再赋值仍然会失败。

额外属性检查更像是针对刚写出来的对象做一次拼写和意图检查。来源已经是一个变量时,允许它还有其他职责。对象类型文档解释了这一规则。

这是 TypeScript 的静态规则。Python 的 Protocol、TypedDict 和不同检查器有各自行为,不能拿一段 Python 字典赋值冒充相同的编译器实验。

通过检查后,多出来的 age 去哪里了?

还在原对象上。first 的静态类型让当前代码只能按 Named 的接口使用它,没有运行时复制,也没有删字段。

所以,如果把这个对象直接序列化发送出去,age 仍可能被发出去。需要脱敏或只输出 name,就要明确创建输出对象,而不是只给变量补一个类型注解。

想限制配置字段,应该怎么写?

固定配置可以在创建处使用明确类型,或使用 satisfies 做约束检查,让拼错字段尽早被发现。允许扩展字段的结构,则应明确它们的类型,不要为了消除报错随手加入 any 索引签名。

来自网络的数据要另外检查字段、类型与业务条件。类型声明只能检查编译器看得见的代码,不能预知服务器这次返回了什么。

验证时,分别编译字面量、已有变量、缺少字段和错误成员类型,再查看生成的 JavaScript。这样能同时弄清「为什么报错」和「通过以后发生了什么」。

面试官继续追问

有额外属性检查,是不是精确类型?

不是。它是特定场景里的检查,不保证对象只能包含这些字段,也不会清理输入。

as 能把缺少的字段补出来吗?

不能,断言没有创建字段的能力。它只是改变编译器如何看待表达式。

两个空接口可以互相赋值吗?

通常可以,因为没有需要区分的成员。确实需要区分业务身份时,要使用带实际约束的品牌类型等方案,并理解其静态边界。

面试速记卡

  • 结构化类型:检查目标所需要的成员。
  • 新鲜字面量:额外属性检查帮助发现可疑字段。
  • 已有变量:多成员可能兼容,缺成员或类型错误仍会失败。
  • 运行时:类型注解不会删除属性或验证网络响应。
  • 安全输出:明确构造需要发送的字段。

公司面试真题

这道题暂未收录可核验的公司真题来源。你可以先阅读本文解析,或浏览已收录的公司面试真题。

浏览公司面试真题 →
简历汪永久免费在线制作简历,模板直接套用、导出无水印,永久免费、下载免费,不需要付费解锁任何功能。去写简历