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

如何在对象中实现TypeScript类型守卫并返回附加信息?

带附加信息的TypeScript类型守卫实现方案

问题场景

我想实现带附加信息的类型守卫,尝试了以下代码,但TypeScript不允许把返回对象里的result设为anything is Something,只能设为boolean,想知道如何实现需求:

type Something = string | number;

const isSomething = (anything: unknown): {
    result: anything is Something,
    additionalInfo: any
} => {
    // ... 实现逻辑
}

// 使用场景
const afterTypeGuard = isSomething(thing);
if (afterTypeGuard.result === true) {
    return {
        info: afterTypeGuard.additionalInfo,
        length: thing.length, // 希望这里thing被推断为Something类型
    }
} else {
    return (thing + 32) * 3; // 希望这里thing被推断为非Something类型
}

可行解决方案

方案1:返回区分联合类型(Discriminated Union)

利用TypeScript的区分联合类型,用result作为区分符,让TS能根据它的true/false自动窄化输入参数的类型。

修改后的代码示例:

type Something = string | number;

// 定义区分联合类型的返回结构
type IsSomethingResult<T> = 
  | { 
      result: true; 
      additionalInfo: any; 
      // result为true时,标记值为Something类型
      value: T & Something 
    }
  | { 
      result: false; 
      additionalInfo: any; 
      // result为false时,标记值为非Something类型
      value: Exclude<T, Something> 
    };

const isSomething = <T>(anything: T): IsSomethingResult<T> => {
    // 类型判断逻辑示例
    if (typeof anything === 'string' || typeof anything === 'number') {
        return {
            result: true,
            additionalInfo: `当前类型:${typeof anything}`,
            value: anything as T & Something
        };
    } else {
        return {
            result: false,
            additionalInfo: `未知类型:${typeof anything}`,
            value: anything as Exclude<T, Something>
        };
    }
};

// 使用示例
const thing: unknown = 'hello';
const guardResult = isSomething(thing);

if (guardResult.result) {
    // 这里guardResult.value会被推断为string | number
    console.log({
        info: guardResult.additionalInfo,
        length: typeof guardResult.value === 'string' ? guardResult.value.length : '数值类型无length属性'
    });
} else {
    // 这里guardResult.value是排除Something后的类型
    console.log(`非目标类型处理:${guardResult.value}`);
}

方案2:通过参数传递附加信息容器

如果不想返回包含值的对象,可以用引用类型参数来存储附加信息,同时保留传统类型守卫的写法:

type Something = string | number;

// 定义存储附加信息的容器接口
interface GuardMeta {
    additionalInfo?: any;
}

// 传统类型守卫函数,同时修改传入的meta对象存储附加信息
const isSomething = (anything: unknown, meta: GuardMeta): anything is Something => {
    if (typeof anything === 'string' || typeof anything === 'number') {
        meta.additionalInfo = `匹配类型:${typeof anything}`;
        return true;
    } else {
        meta.additionalInfo = `不匹配类型:${typeof anything}`;
        return false;
    }
};

// 使用示例
const thing: unknown = 456;
const meta: GuardMeta = {};

if (isSomething(thing, meta)) {
    console.log({
        info: meta.additionalInfo,
        value: thing // 此处thing已被推断为string | number
    });
} else {
    console.log(`错误提示:${meta.additionalInfo}`);
}

为什么原写法不生效?

TypeScript的类型谓词(比如anything is Something)只能直接作为函数的返回类型,不能作为对象属性的类型。这是因为类型守卫的逻辑依赖于函数返回值和参数之间的直接关联,对象属性无法触发TS的类型窄化机制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 20:27:59