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

TypeScript类型转换函数写法:为何instanceof不适用于接口及正确方案

问题

我写了一段TypeScript代码,想用instanceof判断参数的接口类型,但完全不起作用。代码如下:

interface PetrolEngineProperties {
    cylinders: number;
    capacity: number;
}

interface ElectricEngineProperties {
    numberOfBatteries: number;
    batteryCellSize: number;
}

function initializeCarEngine(engineProperties: PetrolEngineProperties | ElectricEngineProperties) {
    if (engineProperties instanceof ElectricEngineProperties) {
        // 处理电动引擎逻辑
    } else if (engineProperties instanceof PetrolEngineProperties) {
        // 处理燃油引擎逻辑
        console.log('Petrol engine was started');
    }
}

想请教:为什么instanceof判断接口类型会失效?这类带类型分支的函数该怎么写才规范?

为什么instanceof无法判断接口类型?

TypeScript的接口是编译时专属的类型定义,编译成JavaScript后,所有接口相关的代码都会被彻底移除——JavaScript运行时根本不知道这些接口的存在。而instanceof是JavaScript的运行时运算符,它只能判断对象是否是某个构造函数(类)的实例,依赖的是对象的原型链信息。接口没有对应的构造函数,自然没法用instanceof来判断。

规范写法

1. 属性检查式类型守卫

通过检查对象是否包含某个接口特有的属性,让TypeScript自动收窄类型,这是最常用的方式:

interface PetrolEngineProperties {
    cylinders: number;
    capacity: number;
}

interface ElectricEngineProperties {
    numberOfBatteries: number;
    batteryCellSize: number;
}

function initializeCarEngine(engineProperties: PetrolEngineProperties | ElectricEngineProperties) {
    // 检查电动引擎特有的属性
    if ('numberOfBatteries' in engineProperties) {
        // 这里TypeScript会自动识别engineProperties为ElectricEngineProperties类型
        console.log(`电动引擎,电池数量:${engineProperties.numberOfBatteries}`);
    } else {
        // 自动识别为PetrolEngineProperties类型
        console.log(`燃油引擎,气缸数:${engineProperties.cylinders}`);
        console.log('Petrol engine was started');
    }
}

2. 自定义类型守卫函数

如果需要更复杂的判断逻辑,可以写一个自定义的类型守卫函数,明确告诉TypeScript如何判断类型:

interface PetrolEngineProperties {
    cylinders: number;
    capacity: number;
}

interface ElectricEngineProperties {
    numberOfBatteries: number;
    batteryCellSize: number;
}

// 自定义类型守卫:判断是否为电动引擎属性
function isElectricEngine(properties: any): properties is ElectricEngineProperties {
    return 'numberOfBatteries' in properties && 'batteryCellSize' in properties;
}

// 自定义类型守卫:判断是否为燃油引擎属性
function isPetrolEngine(properties: any): properties is PetrolEngineProperties {
    return 'cylinders' in properties && 'capacity' in properties;
}

function initializeCarEngine(engineProperties: PetrolEngineProperties | ElectricEngineProperties) {
    if (isElectricEngine(engineProperties)) {
        console.log(`电动引擎,电池单体容量:${engineProperties.batteryCellSize}`);
    } else if (isPetrolEngine(engineProperties)) {
        console.log(`燃油引擎,排量:${engineProperties.capacity}`);
        console.log('Petrol engine was started');
    }
}

3. 改用类代替接口(如果需要运行时类型)

如果确实需要用instanceof判断,那可以把接口改成类——类编译后会保留构造函数和原型链,这样instanceof就能正常工作:

class PetrolEngineProperties {
    constructor(public cylinders: number, public capacity: number) {}
}

class ElectricEngineProperties {
    constructor(public numberOfBatteries: number, public batteryCellSize: number) {}
}

function initializeCarEngine(engineProperties: PetrolEngineProperties | ElectricEngineProperties) {
    if (engineProperties instanceof ElectricEngineProperties) {
        console.log(`电动引擎,电池数量:${engineProperties.numberOfBatteries}`);
    } else if (engineProperties instanceof PetrolEngineProperties) {
        console.log(`燃油引擎,气缸数:${engineProperties.cylinders}`);
        console.log('Petrol engine was started');
    }
}

// 使用示例
const petrolEngine = new PetrolEngineProperties(4, 2.0);
initializeCarEngine(petrolEngine);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 05:47:22