Skip to content

TS 术语解释

TypeScript 文档和社区讨论中频繁出现一些专业术语,理解这些术语有助于读懂错误信息、官方文档以及他人代码。

Assignability(可赋值性)

描述一个类型的值是否可以赋给另一个类型的变量。TS 的类型检查本质上就是在做 assignability 判断。

ts
let a: string = 'hello'
let b: string | number = a  // ✅ string 可赋值给 string | number
let c: number = a            // ❌ string 不可赋值给 number

Narrowing(类型收敛)

通过条件判断让 TS 将一个宽泛的类型"收敛"到更具体的类型。常见的收敛方式有 typeofinstanceofin、字面量相等判断等。

ts
function print(val: string | number) {
  if (typeof val === 'string') {
    // 此处 val 被收敛为 string
    console.log(val.toUpperCase())
  }
}

Widening(类型扩展)

与 Narrowing 相反,TS 在某些场景下会自动将字面量类型"扩宽"为对应的基础类型。

ts
let a = 'hello'  // 推断为 string,而非字面量类型 'hello'
const b = 'hello' // 推断为字面量类型 'hello',const 阻止了扩宽

Type Inference(类型推断)

TS 自动根据值或上下文推导出类型,无需手动标注。

ts
const name = 'xiaoming'       // 推断为 string
const nums = [1, 2, 3]        // 推断为 number[]
const add = (a: number, b: number) => a + b  // 返回值推断为 number

Structural Typing(结构类型 / 鸭子类型)

TS 不通过类名判断类型兼容性,而是通过**结构(属性的形状)**来判断。只要结构匹配,类型就兼容。

ts
interface Point {
  x: number
  y: number
}

function logPoint(p: Point) {
  console.log(p.x, p.y)
}

// 没有显式声明 implements Point,但结构匹配,可以直接传入
const pos = { x: 10, y: 20, z: 30 }
logPoint(pos)  // ✅

Nominal Typing(名义类型)

与 Structural Typing 相对,Java/C# 等语言采用名义类型:即使结构完全相同,不同名称的类型也不兼容。TS 默认不是名义类型,但可以用 brand 技术模拟。

Type Alias vs Interface(类型别名 vs 接口)

两者都可以描述对象形状,区别在于:

对比点type aliasinterface
扩展方式& 交叉类型extends 继承
声明合并❌ 不支持✅ 同名 interface 自动合并
描述联合/元组

Discriminated Union(判别联合)

联合类型中每个成员都包含一个相同的字面量属性(discriminant),TS 可以通过这个属性做精确的类型收敛。也叫 Tagged Union。

ts
type Result =
  | { status: 'ok'; data: string }
  | { status: 'error'; message: string }

function handle(result: Result) {
  if (result.status === 'ok') {
    console.log(result.data)   // 收敛为第一个成员
  } else {
    console.log(result.message) // 收敛为第二个成员
  }
}

Exhaustiveness Check(详尽性检查)

配合 never 类型,确保联合类型的所有分支都被处理到。当后续新增了联合成员但忘记处理时,TS 会在编译期报错。

ts
function handle(result: Result) {
  switch (result.status) {
    case 'ok': return result.data
    case 'error': return result.message
    default:
      const _exhaustive: never = result  // 如果 Result 新增了成员,这里会报错
      return _exhaustive
  }
}

Covariance & Contravariance(协变与逆变)

描述泛型类型在子类型关系中的变化方向。

  • 协变(Covariant):子类型关系"方向一致"。函数返回值是协变的:如果 CatAnimal 的子类型,那么 () => Cat 也是 () => Animal 的子类型。
  • 逆变(Contravariant):子类型关系"方向相反"。函数参数是逆变的:(animal: Animal) => void(cat: Cat) => void 的子类型。
ts
type AnimalFn = (a: Animal) => void
type CatFn = (c: Cat) => void
// 参数逆变:接受更宽泛参数的函数,可以赋给接受更具体参数的变量

在 TS 中,函数参数默认是双变(bivariant)的,开启 strictFunctionTypes 后才会严格按逆变处理。

Declaration Merging(声明合并)

同名的 interfacenamespace 等声明,TS 会自动将它们合并为一个类型。常用于为第三方库扩展类型定义。

ts
interface User {
  name: string
}

interface User {
  age: number
}

// 合并后等价于 { name: string; age: number }
const user: User = { name: 'xiaoming', age: 18 }

Conditional Types(条件类型)

语法类似三元表达式,根据类型关系返回不同的类型。

ts
type IsString<T> = T extends string ? 'yes' : 'no'

type A = IsString<string>   // 'yes'
type B = IsString<number>   // 'no'

Infer(类型推断关键字)

在条件类型中使用 infer 关键字,从类型中"提取"出一个子类型。ReturnTypeParameters 等内置工具类型底层都依赖 infer

ts
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never

type Fn = () => string
type Result = ReturnType<Fn>  // string

Mapped Types(映射类型)

遍历已有类型的属性,生成一个新类型,语法为 [K in keyof T]PartialRequiredReadonly 等工具类型都是映射类型。

ts
type Optional<T> = {
  [K in keyof T]?: T[K]
}
// 等价于内置的 Partial<T>

Template Literal Types(模板字面量类型)

用模板字符串语法操作字符串字面量类型,可以做类型级别的字符串拼接。

ts
type EventName = 'click' | 'focus' | 'blur'
type Handler = `on${Capitalize<EventName>}`
// 'onClick' | 'onFocus' | 'onBlur'

Ambient Declaration(环境声明)

使用 declare 关键字声明一个类型或变量,告诉 TS "这个东西在运行时存在,但不由我来提供实现"。常见于 .d.ts 文件中。

ts
// 声明一个全局变量,不提供实现
declare const __VERSION__: string

// 声明一个模块
declare module '*.svg' {
  const content: string
  export default content
}

Type Predicate(类型谓词)

函数返回值为 arg is SomeType 形式,告诉 TS 当函数返回 true 时,参数就是该类型。是实现自定义类型守卫的方式。

ts
function isString(val: unknown): val is string {
  return typeof val === 'string'
}

function print(val: string | number) {
  if (isString(val)) {
    console.log(val.toUpperCase())  // val 被收敛为 string
  }
}

Index Signature(索引签名)

描述一个对象可以用任意 key 访问,同时指定 key 和 value 的类型。

ts
interface StringMap {
  [key: string]: string
}

const map: StringMap = { name: 'xiaoming', city: 'beijing' }

Branded Types(品牌类型)

通过给类型附加一个虚构属性来模拟名义类型,防止结构相同但语义不同的类型被混用。

ts
type UserId = string & { readonly __brand: 'UserId' }
type OrderId = string & { readonly __brand: 'OrderId' }

function getUser(id: UserId) {}

const orderId = '123' as OrderId
getUser(orderId)  // ❌ 类型不匹配,即使底层都是 string