unknown、any、never 各自是什么语义
What do unknown, any and never each mean
一句话:unknown 是 「还不知道是什么,用之前必须先证明」;any 是 「放弃检查,双向放行」;never 是「不可能有值」。 三个词各占类型系统的一个极端。
放进类型层级看:
unknown是顶类型(top type):任何值都能赋给它; 但不先收窄,它什么都做不了 —— 连u.toUpperCase()都编译不过。never是底类型(bottom type):它能赋给任何类型, 但没有类型能赋给它 —— 因为它根本没有值。any不在层级里,它是关掉检查的开关: 双向都能赋,而且会传染 —— 碰过 any 的表达式结果还是 any, 一处 any 能顺着数据流污染一整个模块。
catch (e) 怎么处理:strict 模式下 (TS 4.4 起的 useUnknownInCatchVariables) e 是 unknown,因为 JS 允许 throw 任何值。直接读e.message 编译不过;标准写法是e instanceof Error 收窄后读 message, else 分支 String(e) 兜底。推而广之: JSON.parse 的结果、API 响应、一切外部输入, 入口处都该标 unknown,收窄之后再进业务代码 —— unknown 是边界上的类型。
会追问:「void 和 never 什么区别?」—— void 是正常返回、只是不带值;never 是根本不会正常返回 (throw 或死循环)。「never 还有什么用?」—— 上一题的穷尽检查,加上在 Exclude 里当删除用: never 是空联合,并进联合就消失。 「为什么宁用 unknown 不用 any?」—— unknown 把「先检查再用」变成编译器强制的动作; any 把它变成自觉,而自觉在赶工期的时候最先消失。
In one line: unknown means “not known yet — prove it before you use it”; any means “checking abandoned, both directions waved through”; never means “no value can exist here”. Three words, three extremes of the type system.
Placed in the type hierarchy:
unknownis the top type: every value is assignable to it; but until you narrow it, it can do nothing — evenu.toUpperCase()refuses to compile.neveris the bottom type: it is assignable to everything, yet nothing is assignable to it — because it has no values at all.anysits outside the hierarchy; it is the switch that turns checking off: assignable both ways, and contagious — an expression that touches any becomes any, and one any can pollute a whole module along the data flow.
Handling catch (e): under strict mode (useUnknownInCatchVariables, since TS 4.4) e is unknown, because JS lets you throw anything. Reading e.message directly does not compile; the standard shape is narrowing with e instanceof Error before touching message, with String(e) as the else fallback. Generalize it: the result of JSON.parse, API responses, all external input should enter as unknown and get narrowed before reaching business code — unknown is the type for boundaries.
Follow-up: “void versus never?” — void returns normally, just without a value; never does not return normally at all (it throws, or loops forever). “What else is never for?” — the exhaustiveness check from the previous card, plus playing deletion inside Exclude: never is the empty union, so merging it in makes members disappear. “Why unknown over any?” — unknown turns check-before-use into something the compiler enforces; any turns it into self-discipline, and self-discipline is the first thing to go when a deadline lands.