首页 > 解决方案 > 处理联合与交叉打字稿的问题

问题描述

我正在尝试用几个方法构建一个接口,然后根据传入的数据作为该对象的键之一调用这些方法。

这是我的类型:

type LogicalFunction<T> = (args: T) => string;

export interface LogicalFunctions
  extends Record<string, (args: QueryObject & QueryObject[]) => string> {
  $not: LogicalFunction<QueryObject>;
  $and: LogicalFunction<QueryObject[]>;
  $or: LogicalFunction<QueryObject[]>;
}

这是我正在使用的对象:

export const logicalFunctions: LogicalFunctions = {
  $not: (expression: QueryObject) => `NOT(${queryBuilder(expression)})`,
  $and: (args: QueryObject[]) => `AND(${queryBuilder(args)})`,
  $or: (args: QueryObject[]) => `OR(${queryBuilder(args)})`,
};

最后,我实际调用函数的地方:

if (
  key in logicalFunctions 
  && (isQueryObject(val) || (val instanceof Array && val.every(v => isQueryObject(v))))
) { logicalFunctions[key](val); }

但正如我写的那样,我从 Typescript 编译器收到以下错误:

Argument of type 'QueryObject | QueryObject[]' is not assignable to parameter of type 'QueryObject & QueryObject[]'

我不确定我是否只是用某种反模式写了这个,或者我只是错过了一些东西。任何帮助或指导将不胜感激:)

标签: typescriptcompiler-errorsstatic-typingunion-types

解决方案


QueryObject & QueryObject[]意味着参数必须同时是一个QueryObject和一个数组QueryObjects。很可能这是不可能的。

QueryObject | QueryObject[]表示参数是一个QueryObject或一个数组QueryObjects。这可能就是你想要的。

在此示例中可在 Typescript Playground 中查看

type T = number | T[]
const t0:T&T[] = [2]   // OK
const t1:T&T[] = 2     // NG

type U = number
const u0:U&U[] = [2]   // NG
const u1:U&U[] = 2     // NG

const uu0:U|U[] = [2]   // OK
const uu1:U|U[] = 2     // OK

variablet0既是 aT又是T[](array of T) - 只是为了向您展示这样的事情是可能的。 t1, u0, 和u1都是编译错误。

不过,uu0uu1都OK。


推荐阅读