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

TypeScript参数类型识别:如何优化属性存在判断逻辑?

TypeScript 优化类型判断逻辑的惯用写法

问题背景

现有代码中需要判断args是否已定义且包含actions属性,当前使用hasOwnProperty并禁用了eslint规则,希望用TypeScript惯用写法重构,让代码更清晰安全:

class Actions { actions: string[] }
type Argument = object | Actions;

export class GetFilesContext implements IExecutable {
   execute( args: Argument, response: ServerResponse<IncomingMessage> ): void {
      ...
      // eslint-disable-next-line no-prototype-builtins
      if( args && args.hasOwnProperty( "actions" )) {
         ctxt.actions.length = 0;
         ctxt.actions.push( ...(args as Actions).actions );
      }
      response.end( JSON.stringify( ctxt ));
   }
}

解决方案

1. 自定义类型守卫(最推荐,TypeScript原生支持)

编写类型谓词函数,让TypeScript自动推导类型,无需手动断言:

class Actions { actions: string[] = [] } // 建议初始化属性避免undefined
type Argument = object | Actions;

// 自定义类型守卫函数
function isActions(arg: Argument): arg is Actions {
  // 先判断非空,再判断是对象类型,最后检查是否包含actions属性
  return arg !== null && typeof arg === 'object' && 'actions' in arg;
}

export class GetFilesContext implements IExecutable {
  execute(args: Argument, response: ServerResponse<IncomingMessage>): void {
    // ...
    if (isActions(args)) {
      ctxt.actions.length = 0;
      ctxt.actions.push(...args.actions); // 无需类型断言,TypeScript自动识别为Actions类型
    }
    response.end(JSON.stringify(ctxt));
  }
}

这种方式既安全又清晰,后续所有用到args的地方都会自动获得类型提示,避免类型错误。

2. 直接使用in操作符(简洁写法)

如果不想单独写类型守卫函数,可以直接用in操作符做条件判断,无需禁用eslint:

export class GetFilesContext implements IExecutable {
  execute(args: Argument, response: ServerResponse<IncomingMessage>): void {
    // ...
    if (args && 'actions' in args) {
      ctxt.actions.length = 0;
      ctxt.actions.push(...(args as Actions).actions);
    }
    response.end(JSON.stringify(ctxt));
  }
}

'actions' in args会检查对象自身或原型链上是否存在该属性,对于当前的Argument类型来说足够准确,写法比hasOwnProperty更简洁。

3. 正确使用instanceof(仅限类实例场景)

如果args是通过new Actions()创建的类实例,instanceof可以直接生效(之前失败可能是因为args不是类实例,而是普通对象):

export class GetFilesContext implements IExecutable {
  execute(args: Argument, response: ServerResponse<IncomingMessage>): void {
    // ...
    if (args instanceof Actions) {
      ctxt.actions.length = 0;
      ctxt.actions.push(...args.actions);
    }
    response.end(JSON.stringify(ctxt));
  }
}

注意:这种方式只适用于args是Actions类的实例对象,如果args是API传入的普通JSON对象(plain object),则instanceof不生效,此时建议用前两种方法。

补充说明

  • 单独用typeof无法区分object和Actions实例,因为两者的typeof结果都是'object',所以需要结合其他判断条件。
  • 原代码中hasOwnProperty需要禁用eslint是因为存在安全风险(若对象重写了hasOwnProperty方法),更安全的替代写法是Object.prototype.hasOwnProperty.call(args, 'actions'),但不如in或类型守卫简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 23:42:22