类型推断就是 TS 自动帮你“猜”类型,不用你手动写。编译器会根据代码上下文、赋值内容、函数返回逻辑来推导。比如你写 let num = 10,TS 直接推断成 number;函数里 return 字符串,就自动推返回值是 string。 它分基础推断和上下文推断,前者看变量赋值,后者看使用场景,比如事件回调里的参数不用写类型也能识别。推断的核心是“从已知推未知”,既简化代码,又不丢类型安全,简单场景完全不用写注解,复杂逻辑再手动补充就行。
最简单说:类型推导是 TS 自动猜,类型注解是你手动写。 类型推导是被动的,编译器根据赋值、逻辑自己确定类型,代码更简洁,比如 let str = "abc" 自动是 string。类型注解是主动声明,强制规定类型,比如 let str: string = "abc",更明确、更严谨。 推导适合简单变量、常规逻辑;注解适合函数参数、返回值、复杂对象、联合类型,防止 TS 猜错。两者不是对立的,而是配合使用:简单用推导,复杂 / 关键位置用注解,兼顾简洁和安全。
类型断言就是你告诉 TS“我比你更清楚这个类型”,强制覆盖推断,但非常容易破坏类型安全,一定要慎用。 首先,只能断言成更具体或更宽泛的类型,不能跨类型乱转;其次,优先用 as 语法,别用尖括号写法,会和 JSX 冲突;然后,绝对不要“骗”TS,比如把不确定的类型硬转成目标类型,会直接导致运行时报错。 能用类型守卫就别用断言,断言只适合你百分百确定类型的场景,它只在编译时生效,不会改变运行时的数据结构。
TS 是结构化类型系统,只看结构不看名字,和 Java、C# 那种名义类型不一样。 只要两个类型的结构、字段、方法匹配,就算名字不同,也互相兼容。比如一个接口 {name: string} 和一个类 {name: string} 是兼容的。函数兼容性看参数和返回值:参数少的兼容多的,返回值子类型兼容父类型。 另外,子类型可以赋值给父类型,多属性兼容少属性。泛型也看结构,枚举是例外,属于名义类型。核心就是:结构对上,就兼容。
never 代表永远不会发生的类型,是 TS 里最底层的类型。 比如永远抛出错误的函数、死循环函数,返回值都是 never;它也可以用来收束联合类型,在 switch 里穷尽所有 case 后,default 里赋值给 never,漏写 case 就会编译报错。 还能标记不可能到达的代码路径,比如一个函数执行完必抛错,后面的代码就会被识别为 never。never 的核心作用是做类型兜底检查,帮你发现逻辑遗漏、不可达代码,提升类型严谨性。
想减少运行时错误,核心是让 TS 尽可能管住你的代码。 首先开启严格模式 strict: true,打开严格空检查;少用 any,能用 unknown 就用 unknown,配合类型守卫缩小范围。外部数据(接口、表单、localStorage)一定要用 zod、yup 做运行时校验,TS 只管编译时。 少用类型断言,多用接口、类型别名定义复杂结构;穷尽联合类型,用 never 兜底;函数参数、返回值尽量写注解,避免隐式推断出错。再配合 ESLint 的 TS 规则,从编译阶段就拦住大部分问题。