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

TypeScript运行时类型自省:如何区分NodeFilter与EdgeFilter类型函数

方案1:拆分API,从设计层面规避运行时判断 (最推荐)

完全不需要做运行时类型校验,编译期就能完成所有类型检查,语义清晰调用成本极低:

class Graph {
  // 独立的节点过滤方法
  filterNodes(filter: NodeFilter): Graph {
    const newNodes = this.nodes.filter(filter)
    return new Graph(newNodes, [...this.edges])
  }

  // 独立的边过滤方法
  filterEdges(filter: EdgeFilter): Graph {
    const newEdges = this.edges.filter(filter)
    return new Graph([...this.nodes], newEdges)
  }

  // 可选保留原统一入口做兼容
  filter(filter: NodeFilter | EdgeFilter): Graph {
    // 内部用后面的类型判断逻辑实现即可
  }
}

这个方案没有任何运行时额外开销,也不会出现调用方传错过滤器的问题,是所有方案里性价比最高的选择。

方案2:带标记的过滤器封装(适合需要保留统一filter入口的场景)

你之前给函数加type属性的思路可以通过工厂函数优化,避免手动加标记漏写的问题:

// 定义带标记的过滤器类型
type NodeFilter = {
  type: 'NodeFilter'
  (node: Node): boolean
}
type EdgeFilter = {
  type: 'EdgeFilter'
  (edge: Edge): boolean
}

// 工厂函数自动加标记,强制类型校验
const createNodeFilter = (filter: (node: Node) => boolean): NodeFilter => {
  return Object.assign(filter, { type: 'NodeFilter' as const })
}
const createEdgeFilter = (filter: (edge: Edge) => boolean): EdgeFilter => {
  return Object.assign(filter, { type: 'EdgeFilter' as const })
}

// 类型守卫实现运行时判断
function isNodeFilter(filter: unknown): filter is NodeFilter {
  return typeof filter === 'function' && (filter as any).type === 'NodeFilter'
}
function isEdgeFilter(filter: unknown): filter is EdgeFilter {
  return typeof filter === 'function' && (filter as any).type === 'EdgeFilter'
}

// 使用示例
const filter = createNodeFilter(node => node.weight > 10)

这个方案比手动给每个函数加属性更安全,TS编译期会强制你走工厂函数创建过滤器,不会出现漏加标记的问题。

方案3:可调用类实例(适合过滤器需要携带状态的复杂场景)

你提到的可调用类方案完全可行,运行时可以直接用instanceof判断,不需要额外写类型守卫:

abstract class BaseFilter {
  abstract type: 'NodeFilter' | 'EdgeFilter'
  abstract exec(value: Node | Edge): boolean
}

class NodeFilter extends BaseFilter {
  type: 'NodeFilter' = 'NodeFilter'
  constructor(private filterFn: (node: Node) => boolean) { super() }
  exec(node: Node): boolean {
    return this.filterFn(node)
  }
}

class EdgeFilter extends BaseFilter {
  type: 'EdgeFilter' = 'EdgeFilter'
  constructor(private filterFn: (edge: Edge) => boolean) { super() }
  exec(edge: Edge): boolean {
    return this.filterFn(edge)
  }
}

// 运行时判断逻辑
if (filter instanceof NodeFilter) {
  nodes = nodes.filter(n => filter.exec(n))
} else if (filter instanceof EdgeFilter) {
  edges = edges.filter(e => filter.exec(e))
}

这个方案适合过滤器需要存储额外配置、复用过滤逻辑的场景,缺点是比纯函数多了一点类实例的开销。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 04:57:02