Chai 中文文档 下载 App

类型判断 a / an / typeOf / instanceof - 检查值的类型信息

三种类型断言方法

Chai 提供三个不同粒度的类型检查断言:

方法检查内容参数示例
.a / .antypeof 类型字符串类型小写字符串expect(x).to.be.a('string')
.typeOf同 .a / .an(别名)类型小写字符串expect(x).to.typeOf('number')
.instanceOf / .instanceof原型链构造函数expect(x).to.be.an.instanceOf(Error)

.a / .an 的区别

两者完全等价,根据后面的类型字符串发音选择:

expect('hello').to.be.a('string');   // 'string' 辅音开头 → a
expect(42).to.be.a('number');        // 'number' 辅音开头 → a
expect([1,2]).to.be.an('array');     // 'array' 元音开头 → an
expect(null).to.be.a('null');        // 'null' 辅音开头 → a

这完全是可读性的语法糖——用错 a/an 不会导致断言失败。expect('hello').to.be.an('string') 照样通过。

支持的 typeof 类型字符串

// 原始类型
expect('hello').to.be.a('string');
expect(42).to.be.a('number');
expect(true).to.be.a('boolean');
expect(undefined).to.be.an('undefined');
expect(null).to.be.a('null');

// 注意:typeof null 在 JS 中返回 'object',但 Chai 做了特殊处理
// expect(null).to.be.a('object') 会失败
// expect(null).to.be.a('null') 才是正确的
// 函数
expect(function() {}).to.be.a('function');
expect(async () => {}).to.be.a('function');
expect(() => 1).to.be.a('function');

// 符号和 BigInt
expect(Symbol('x')).to.be.a('symbol');
expect(1n).to.be.a('bigint');
// 对象和数组
expect({}).to.be.an('object');
expect([]).to.be.an('array');     // array 不是 object!Chai 特殊处理
expect(/regex/).to.be.an('object');  // RegExp 是 object
expect(new Date()).to.be.an('object');

.typeOf 方法形式

如果你更喜欢方法调用形式(assert 风格的接口):

expect('hello').to.be.typeOf('string');  // 方法形式
// 等价于
expect('hello').to.be.a('string');       // 属性形式

两者功能完全相同。

.instanceOf 检查原型链

.instanceOf 对应 JavaScript 的 instanceof 运算符:

class Animal {}
class Dog extends Animal {}

const dog = new Dog();

expect(dog).to.be.an.instanceOf(Dog);     // 通过
expect(dog).to.be.an.instanceOf(Animal);  // 通过(原型链)
expect(dog).to.be.an.instanceOf(Object);  // 通过(所有对象都是 Object 实例)

注意:.instanceof 也是合法的别名(少一个 f):

expect(error).to.be.an.instanceof(Error);

大小写也不敏感:.instanceOf / .instanceof / .InstanceOf 都行。

null 和 undefined 的特殊处理

JavaScript 的 typeof null 历史遗留问题——返回 'object'。Chai 为此做了特殊处理:

// ✅ 正确
expect(null).to.be.a('null');
expect(undefined).to.be.an('undefined');

// ❌ 会失败
expect(null).to.be.an('object');  // Chai 识别 null 的特殊性

这是 Chai 帮你处理的常见陷阱之一。

.not + 类型检查

expect(42).to.not.be.a('string');
expect({}).to.not.be.an('array');
expect(err).to.not.be.an.instanceOf(TypeError);

类型组合检查

一次检查多个类型:

// 用 .satisfy 自定义谓词
expect(value).to.satisfy(v => typeof v === 'string' || typeof v === 'number');

// 或者先检查值再检查类型
if (typeof value === 'string') {
  expect(value).to.match(/^\d+$/);
} else {
  expect(value).to.be.a('number');
}

assert 风格中的类型检查

const assert = require('chai').assert;

assert.typeOf(value, 'string');
assert.notTypeOf(value, 'number');
assert.instanceOf(obj, SomeClass);
assert.notInstanceOf(obj, SomeClass);

Array 是一个特殊类型

注意在 Chai 中,数组的类型是 'array' 而不是 'object':

expect([]).to.be.an('array');       // 通过
expect([]).to.be.an('object');      // 失败

这符合直觉但不完全等同于原生 JS 行为(typeof [] 返回 'object')。Chai 做了这个改进。

下一步