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

使用动态运算符时无法正确为JSON Logic编写TypeScript类型

解决json-logic-js类型定义中动态运算符的TypeScript编译错误

问题原因

当使用动态属性名创建RulesLogic对象时,TypeScript会将对象推断为{ [x: string]: ... }这类索引签名类型,但RulesLogic是由所有合法运算符对应的单属性对象组成的联合类型(例如{ '==': Expression[] } | { '>=': Expression[] } | ... | { log: JsonLogicLogOptions })。索引签名类型无法匹配联合类型的结构,因此触发类型不兼容错误。

解决方案

1. 类型断言(快速解决)

直接将动态创建的对象断言为RulesLogic,前提是你能确保运算符属于合法的ReservedOperations集合:

const op: ReservedOperations[] = ['==','>=','<=','===']
const dynamicOperator = op[1]

const dynamicRule: RulesLogic = {
  [dynamicOperator]: [{var:'one'},1]
} as RulesLogic;

2. 类型守卫(更安全)

创建类型守卫函数,让TypeScript确认动态运算符的合法性,避免非法运算符的隐患:

import { ReservedOperations, RulesLogic } from 'json-logic-js';

function isValidOperator(op: string): op is ReservedOperations {
  // 枚举所有ReservedOperations包含的运算符
  const validOps: ReservedOperations[] = [
    '==', '===', '!=', '!==', '>', '>=', '<', '<=',
    'and', 'or', 'not', 'if', '?:', 'switch', 'case',
    'null', 'undefined', '!!', 'log', 'var', 'missing',
    'missing_some', 'map', 'filter', 'reduce', 'all', 'none', 'some'
  ];
  return validOps.includes(op as ReservedOperations);
}

// 使用示例
const op: ReservedOperations[] = ['==','>=','<=','===']
const dynamicOperator = op[1];

if (isValidOperator(dynamicOperator)) {
  const dynamicRule: RulesLogic = {
    [dynamicOperator]: [{var:'one'},1]
  };
  // 这里可以安全使用dynamicRule
}

3. 泛型函数优化(适用于工厂函数场景)

针对你的工厂函数场景,通过泛型约束运算符类型,再结合类型断言解决:

import { RulesLogic } from 'json-logic-js';

const createRulesLogic = <Op extends '==' | '!='>(operation: Op): RulesLogic => 
  ({ [operation]: [{var:'one'},1] } as Record<Op, unknown> as RulesLogic);

补充说明

报错中提到的Property 'log' is missing是因为RulesLogic联合类型包含了JsonLogicLog类型(对应log运算符),而动态创建的对象显然没有log属性。本质还是TS无法确认动态属性名属于联合类型中的某一个成员,导致无法匹配类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 11:12:55