三块面板:TS 源码 / 写死的 tsc 报错样本(非现场运行)/ 可点跑的等价 JS。断言的本质:你对编译器说“信我,它其实是这个类型”,它照办且不检查——出错你自担。

一、as 不做运行时转换

TS 源码

const raw = '42'
const n = raw as unknown as number   // 双重断言,借 unknown 中转
n.toFixed(2)                          // 编译通过,但运行时 n 还是字符串!
cast.ts:2:11 - error TS2352: Conversion of type 'string' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. 2 const n = raw as number ~~~~~~~~~~~~~
为什么报:直接 string→number 重叠不足会被拒。先 as unknown 再 as number 能绕过——但绕过检查≠值真的变了,运行时它仍是字符串。

等价 JS(去掉类型后可真跑)

[迷你控制台]

二、非空断言 ! 的代价

function f(s?: string) {
  return s!.length   // 你保证 s 一定有值;真传 undefined 就运行时崩
}

三、satisfies:校验又不丢精度

type Route = string | (() => string)
const routes = {
  home: '/',
  about: () => '/about',
} satisfies Record<string, Route>
routes.home      // 类型仍是字面量 '/'(被 satisfies 校验但不被宽化成 string)
routes.about()   // 知道存在、可调用

四、四款工具各就各位

el as HTMLInputElement     // as:改编译器“看法”,不改变运行时值
unknown as unknown as T     // 双重断言:绕过重叠检查,几乎放弃安全(少用)
value!                      // 非空断言:向编译器保证“一定不空”,错了运行时崩
{ ... } as const            // as const:钉死字面量 + 全属性只读
{ ... } satisfies Shape     // satisfies:校验形状,同时保留更精确的推断
优先级记忆:能收窄(is 谓词 / typeof)就别断言;要“校验但不丢精度”用 satisfies;as const 专管字面量钉死;as / ! / 双重断言是最后手段,用一处就该停下来问“能不能改成检查”。