-
我在 TypeScript 里把接口返回定义成成功结果和错误结果的联合类型本以为这下两种情况的字段我都能随便访问了,结果一访问成功结果才有的 data 字段编译器就报错说这个属性在错误结果上不存在,我对着明明是联合类型为什么不让我访问的报错懵了很久,最后才搞懂联合类型在值上是二选一在能安全访问的成员上反而只剩两者的交集的深度复盘
我写接口调用封装,想用 TypeScript 联合类型优雅表达成功和失败两种返回:interface SuccessResult { ok:true; data:string } 和 interface ErrorResult { ok:false; message:string },type ApiResult = SuccessResult | ErrorResult。结果一访问 result…- 0
- 0
-
我在 TypeScript 里给函数参数标了个空对象大括号类型、想表示只收一个对象,结果传数字、传字符串、传布尔值进去编译器全都不报错照单全收,我盯着那对空大括号愣了半天,最后才搞懂这个看着像空对象的类型实际表示的是除了 null 和 undefined 之外几乎任何值的深度复盘
我写了个函数本意只接收一个对象(任意结构都行但至少得是对象、不能是基本类型),很自然把参数类型标成了 {}——直觉里 {} 不就是一个空对象引申为任意对象嘛,以为这样就能限制住只准传对象。可写着发现不对:把 42、hello、true 这些明显不是对象的值传进去编译器一个错都不报,这道我以为加上的只准传对象的约束形同虚设。我以为哪里写错了、反复确认参数类型就是 {},又怀疑 strict 没开也开…- 0
- 0
-
我在 TypeScript 里定义了一个配置对象、method 字段明明写死的就是字符串 GET,可把它传给一个只接受 GET 或 POST 这种联合字面量类型的函数时编译器死活报错说 string 不能赋值,我盯着那个明明白白的 GET 看了半天最后才搞懂编译器早就把我写死的字面量悄悄拓宽成了普通的 string 的深度复盘
我有个函数签名要求传入的请求方法是联合字面量类型 method: GET | POST,只允许这两个确切字符串。我图复用把请求配置抽成对象常量 const config = { url, method: GET },method 我清清楚楚写的就是 GET,然后传给那个函数,以为天经地义能过。结果编译器红线一片:Type string is not assignable to type GET |…- 0
- 0
-
我在 TypeScript 里到处用感叹号非空断言把编译器的红线消掉、它不报错我就以为安全了,结果线上照样满屏 Cannot read properties of undefined 的崩溃,排查很久才彻底想通那个感叹号根本不会在运行时做任何检查、它只是我对编译器单方面许下的一个空头承诺的深度复盘
我曾经特别爱用 TypeScript 的非空断言感叹号:哪里编译器报可能为 null/undefined、画红线,我就在后面点个感叹号告诉它这里一定不是空,红线立刻消失、编译通过,我就觉得搞定了、安全了。直到线上监控满屏都是 Cannot read properties of undefined 的崩溃,而出事的地方恰恰都是我用感叹号搞定过的。比如 users.find(u=>u.id===…- 0
- 0
-
我在 TypeScript 的 catch 块里顺手写了 e.message 想拿错误信息,编译器却报错说对象类型为 unknown,我一度以为是 TS 太死板,后来才明白它是在提醒我一个我从没认真想过的事实——catch 到的东西,根本不保证是个 Error 的深度复盘
我在 TypeScript 里写 try/catch,catch 到异常后很自然想拿错误信息 catch (e) { log(e.message) },在我脑子里 catch 到的当然是错误对象当然有 message。可编译器直接报错 Object is of type unknown 不让访问。我一开始烦躁觉得 TS 太死板,甚至想 (e as Error).message 强转了事。冷静下来查…- 0
- 0
-
我给函数参数和解构都设了默认值,以为这下不管传什么进来都有兜底了,结果一个从接口来的 null 直接穿透了默认值、拿到手还是 null、访问属性当场崩溃,排查半天才发现默认值只认 undefined、根本不认 null 的深度复盘
我写了个 TypeScript 函数接收配置对象,为了健壮给参数和解构都加了默认值,心想无论传不传、传什么都有兜底绝不会出问题。本地用 undefined、不传参数测了一圈默认值都生效,我便放心了。可上线后偏偏崩在我自以为最稳的地方:一个从后端接口返回的字段是 null 被当参数传进来,我设的默认值完全没生效,参数拿到的就是那个 null,紧接着属性访问当场崩溃 Cannot read prope…- 0
- 0
-
我的 TypeScript 代码里一个声明为 Dog 数组的变量,运行时遍历它时竟拿到了一个根本没有 bark 方法的对象、直接报错,排查半天发现是我把它当 Animal 数组传给了一个函数、那函数往里塞了别的动物的深度复盘
我有段处理动物的 TypeScript 代码,基类 Animal、子类 Dog(有 bark)和 Cat(有 meow);我有个 Dog 数组,确信全是狗,遍历时放心调 dog.bark(),写了很久都好好的。可有天线上报错 TypeError: dog.bark is not a function,我懵了——这明明是 Dog 数组、编译器全程绿灯,怎么会遍历出一个没有 bark 的东西?打出数组…- 0
- 0
-
我给一个联合类型加了个新的状态值,以为编译器会提醒我去所有用到它的地方补上处理,结果它一声不吭、那个新状态在好几个 switch 里被悄悄漏掉了:一次没用 never 做穷尽检查的深度复盘
我有个订单状态联合类型 type Status = 'pending' | 'paid',好几处用 switch 分别处理这两种。后来加了已退款状态、把类型改成 'pending' | 'paid' | 'refunded',我想当然以为 TS 会在所有没处理 refunded 的 switch 处…- 0
- 0
-
我用逻辑或给配置项设默认值,用户明明传了一个合法的 0,却被我当成没传替换成了默认值,因为 || 判断的是假值不是是否缺失,而 0、空字符串、false 都是合法却为假的值的深度复盘
我有个配置项 pageSize,为了用户没配时给默认值 20,写得很顺手:const pageSize = config.pageSize || 20。一直好好的,直到有用户反馈:我把 pageSize 配成了 0(业务里 0 表示不分页、返回全部),系统却还是按 20 分页、我的 0 不生效!一看代码就傻眼:config.pageSize 明明是 0,可 0 || 20 的结果是 20——|| …- 0
- 0
-
我在 TypeScript 里用 as 把接口返回的数据断言成了我定义的类型,以为这下类型安全了可以放心用,结果运行时那个字段是 undefined 直接报错,因为 as 根本不做任何检查:一次滥用类型断言的深度复盘
我从后端接口拿到一坨 JSON,为了能有类型地用它,顺手写了 const user = data as User,心想这下 user 就是 User 类型、可以放心 user.profile.name 了。编译一点不报错就上线,结果线上报 TypeError: Cannot read properties of undefined——user.profile 居然是 undefined。排查才发现…- 0
- 0
-
我按索引取数组元素、直接用它的属性,TypeScript 一声没吭,可那个索引越界了、取到的是 undefined,运行时直接炸:一次 TS 索引访问类型漏洞的深度复盘
我有个数组 items: Item[],某处 const item = items[index]; item.name,TS 编译一声没吭。可线上某次 index 因为某个计算越界了(算成 10 而数组只有 5 个),程序当场炸 Cannot read properties of undefined (reading 'name')。既然 items 是 Item[],item…- 0
- 0
-
我用数字枚举定义订单状态,以为类型安全了,结果一个不存在的数字 99 也能传进去、遍历枚举时还莫名多出一倍的项:一次 TypeScript 数字枚举两个坑的深度复盘
我用 TS 数字枚举定义订单状态 enum OrderStatus { Pending, Paid, Shipped }(值默认 0、1、2),以为用了枚举类型就安全了。可线上两件怪事:一个不属于这枚举的数字 99 被传进了参数类型为 OrderStatus 的函数、TS 居然不报错,导致 switch 走到没人料到的分支;用 Object.keys 遍历枚举出来的项数是成员的两倍、还混着数字和字…- 0
- 0
-
我把 productId 当成 userId 传进了查询函数,两个都是 number、TypeScript 一声没吭,直到线上查出了张冠李戴的数据:一次 TS 结构化类型让语义不同的 ID 意外兼容、用品牌类型才拦住的深度复盘
我们有 getUser(userId: number) 和 getProduct(productId: number) 两个函数,一次重构里我手滑把 productId 传给了 getUser,满以为 TypeScript 会拦下这种低级错误,可它一声没吭、编译通过。线上就出现了用商品 ID 查用户、查出张冠李戴数据的诡异现象。查到底才明白这不是 bug:TS 是结构化类型系统,判断两个类型是否兼…- 0
- 0
-
一个图省事用 any 接住的 JSON 数据,像墨水一样把后面一整片代码的类型检查都染没了,拼错的属性名 TS 一声不吭:一次 any 扩散的深度复盘
从 JSON.parse 拿数据图省事声明成 any,后面把 nickname 拼成了 nikename、用错类型,TS 编译却一个错都没报,上线后取到 undefined 页面空白。根因是 any 关闭对这个值的类型检查(任何操作都放行)且会传染:data 是 any,data.user、data.user.profile 派生的还是 any,从那个 any 开始后面一整片代码都悄悄失去了类型检…- 0
- 0
-
一个用联合类型加 switch 处理多种形状的函数,在我新增了一种类型后悄悄漏掉了它、TS 却一声不吭,直到线上才暴露:一次 TypeScript 穷尽检查缺失的深度复盘
给图形联合类型加了三角形,在类型定义和创建处都改了、自信上线,结果三角形面积算错。排查发现那个算面积的 switch 忘了加 triangle 的 case、走了 default 返回 0,而 TS 编译全程一声不吭。根因是 TS 默认不对联合类型做穷尽性检查——一个 switch 漏处理某成员它不报错,加新成员后漏改的地方静默遗漏,我对 TS'改类型自动揪出要改处'的期待落空…- 0
- 0
-
一个把数字枚举的值直接存进数据库的设计,在我往枚举中间插了一个新成员后,让所有历史订单的状态集体错位了一格:一次 TypeScript 枚举持久化的深度复盘
订单状态用 TS 数字枚举、状态值以数字存库。某次在'待支付'和'已支付'间插了个'支付中',发布后大量历史订单状态集体往后错位一格——已发货显示成已支付。根因是 TS 数字枚举不显式赋值时值从 0 自动递增、靠声明顺序决定,往中间插成员让后面所有值 +1,而数据库里历史数据存的旧数字没变、代码却用新枚举去解释,含义被悄悄换掉。本文讲透数…- 0
- 0
-
一个用 as User 把后端返回的 JSON 强转成类型的写法,在字段结构对不上时让 TypeScript 的类型检查彻底成了摆设、运行时崩在 undefined 上:一次类型断言滥用的深度复盘
用户详情页在某些用户身上稳定白屏,报 Cannot read properties of undefined——可代码明明有完整类型声明、编译一个错没报。根因是 const user = await res.json() as User:as 只是类型断言,在编译期单方面告诉编译器'信我这是 User',不做任何运行时检查或转换;后端某些情况没返回 profile,TS 毫不知…- 0
- 0
-
我用数字枚举定义状态,本以为类型很安全,结果一个根本不在枚举里的数字 99 被当成合法状态溜了进来,遍历枚举时还冒出一堆奇怪的数字键,我对着 TypeScript 数字枚举这两个坑排查了大半天的复盘
一个让我对 TypeScript 的 enum 从信任到警惕的坑,隐蔽在 enum 看起来是个限定取值范围保证类型安全的好东西,我以为用了它一个变量就只能是枚举里那几个值,可它既没拦住非法的值溜进来又在运行时生成了一堆我没料到的东西。用数字枚举 enum Status { Active, Inactive, Pending }(0,1,2)。坑1:数字枚举类型居然能接受任意数字,setStatus…- 0
- 0
-
项目开着严格的类型检查,一个本该被拦住的类型错误却溜到了运行时才崩,排查发现是一个 any 沿着数据流一路传染、悄悄关掉了大片代码的类型保护,我对着 any 的传染性这个坑排查大半天的复盘
一个让我对 TypeScript 类型安全到底靠不靠谱重新审视的坑,可怕在我以为开了 TS 开了严格模式代码就被类型系统严严实实保护着,可实际上有一大片代码的类型检查早已在不知不觉中被一个 any 悄悄彻底关闭了。一个访问对象属性的地方访问了根本不存在的属性运行时崩,我困惑 TS 不是该编译时拦住吗?顺着数据往回追找到源头:const data = JSON.parse(jsonStr) 返回 a…- 0
- 0
-
我把一个商品 ID 错传给了需要用户 ID 的函数,TypeScript 全程绿灯没有半点警告,直到线上查错了数据才暴露,我对着结构化类型让语义不同的类型随意互换这个坑排查大半天的复盘
一个让我对 TypeScript 类型系统到底在保护什么重新认识的坑,隐蔽在我犯的是纯粹的逻辑错误(把 A 的 ID 当 B 的 ID 用),而我以为有类型系统罩着的 TS 却完全沉默。代码里有用户 ID 和商品 ID 恰好都是 number。type UserId = number;type ProductId = number;有个 getUserById(id: UserId) 函数,重构时…- 0
- 0
-
我用 as 把后端返回的 JSON 断言成 User 类型,TypeScript 编译一路绿灯,结果上线访问字段直接运行时崩溃白屏,我对着类型断言只骗编译器不做运行时检查排查大半天的复盘
写一个用户中心页面,从后端接口拿当前用户信息再渲染。fetch 拿到 JSON 后,我很自然地写下 return data as User 给它类型,后续代码就有了类型提示和补全。tsc 编译、编辑器全程绿灯,一点错没有。可一上线页面直接白屏,控制台刺眼报错:Cannot read properties of undefined (reading city)、user.getDisplayName…- 0
- 0
-
我用数字枚举判断用户角色,结果第一个角色 Admin 怎么判都是"假"、权限全乱了,我对着 TypeScript 数字枚举的几个坑排查了大半天的复盘
用 TS 写权限判断,定义了 enum Role { Admin, User, Guest },很多地方用 if(user.role) 判断有没有角色/是不是某角色,逻辑看着没毛病,线上却出诡异权限 bug:偏偏 Admin 各种判断都被当成"没角色/假值",管理员权限全乱套。盯着代码反复看,Admin 明明是合法枚举值凭什么 if 判断是 false?排查大半天才理解数字枚举…- 0
- 0
-
TypeScript 里我用下标取数组元素、类型明明是 number,运行时却拿到 undefined 还崩了,我对着数组索引访问的类型不安全排查了大半天的复盘
用 TypeScript 写数据处理,从数组按下标取元素再调它的方法,类型检查一路绿灯、IDE 没任何警告就上线了。运行时却炸:Cannot read properties of undefined。满脸问号:这变量类型明明被 TS 标成 number,怎么会是 undefined?TS 不是号称类型安全吗连"可能是 undefined"都不提示?排查大半天才理解 TS 默认状…- 0
- 0
-
我用 as 把接口返回的数据断言成了想要的类型,编译器一声不吭全绿,上线后却在访问属性时疯狂报 undefined,我对着类型断言排查了大半天的复盘
用 TypeScript 写前端页面,调后端接口拿数据,为了让 TS 别报错、让我能愉快点出属性,我顺手用 as 把接口返回的结果断言成了我定义的类型。编译器立刻安静、IDE 自动补全都有,我以为类型对上稳了。上线后生产监控却疯狂报 Cannot read properties of undefined,就报在那行"类型明明对的"的属性访问上。排查大半天才真正理解 as 的危险…- 2
- 0
TypeScript
幸运之星正在降临...
点击领取今天的签到奖励!
恭喜!您今天获得了{{mission.data.mission.credit}}积分
我的优惠劵
-
¥优惠劵使用时效:无法使用使用时效:
之前
使用时效:永久有效优惠劵ID:×
没有优惠劵可用!
























