You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript核心类型检查原则:为何是结构类型而非鸭子类型?

嘿,这个混淆其实挺普遍的,很多刚接触TypeScript的开发者都会把结构子类型和鸭子类型搞混,我来帮你理清楚两者的核心差异~

TypeScript的结构子类型 vs 真正的鸭子类型

首先得明确一个关键区别:TypeScript用的是静态结构子类型检查,而正宗的鸭子类型是运行时检查,这是两者本质的不同。

1. TypeScript的结构子类型:编译时就搞定的形状匹配

TypeScript手册里确实提到:

TypeScript的核心原则之一是类型检查关注值的形状,这有时被称为“鸭子类型”或“结构子类型”。

但这里的表述其实是因为两者有理念上的相似性——都不纠结于对象的“名义类型”(比如类的名字),而是看它的“形状”(有没有对应的属性、方法)。但本质上,TS的结构类型检查是完全在编译阶段完成的,和运行时毫无关系。

举个直观的例子:

interface Duck {
  quack(): void;
}

function makeQuack(duck: Duck) {
  duck.quack();
}

// 这个对象没有显式实现Duck接口,但形状匹配
const myPetBird = { 
  quack: () => console.log('嘎嘎嘎!'),
  fly: () => console.log('我会飞~')
};

makeQuack(myPetBird); // 编译完全通过

这里TS在编译时就已经确认myPetBird有quack方法,符合Duck接口的形状,根本不会等到代码运行时再去判断。如果我们传一个没有quack的对象,编译阶段直接就会报错,提前帮你发现问题。

2. 真正的鸭子类型:运行时才做的行为检查

正如维基百科所说:

鸭子类型要求类型检查延迟到运行时进行,并且……

鸭子类型是动态语言(比如JavaScript)的特性,它完全不关心静态类型,只看对象在运行时实际能不能做某件事。还是用刚才的例子,换成纯JavaScript的写法:

function makeQuack(duck) {
  // 只有在运行时,才会检查这个对象有没有quack方法
  if (typeof duck.quack === 'function') {
    duck.quack();
  } else {
    throw new Error("这玩意儿不会叫啊!");
  }
}

const myCat = { meow: () => console.log('喵喵喵~') };

makeQuack(myCat); // 编译(如果有的话)不会报错,但运行时会抛出错误

这里没有任何静态检查,只有当代码真正跑起来的时候,才会判断传入的对象是否符合“能嘎嘎叫”的行为——这才是正宗的鸭子类型。

3. 一句话总结

  • TypeScript的结构子类型:静态编译阶段检查,基于值的形状匹配类型,提前拦截错误。
  • 鸭子类型:运行时检查,只关注对象实际行为,和静态类型无关。

所以你的理解完全正确——TypeScript的核心原则是结构类型,手册里提到“鸭子类型”只是因为两者理念相似,但本质上TS作为静态类型语言,和依赖运行时检查的鸭子类型不是一回事。

内容的提问来源于stack exchange,提问作者overexchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:04:06