Typescript误解与ElasticSearch Node客户端

huangapple go评论72阅读模式
英文:

Typescript misunderstanding with ElasticSearch Node Client

问题

使用:

  • NodeJS v16.16.0
  • "@elastic/elasticsearch": "8.7.0"

我想创建一个可以接受多种批量操作的函数。我的目标是确保该函数的输入将对我的索引产生良好的值(这里是 ab)。

以下是我无法正确输入的代码片段:

import { Client } from "@elastic/elasticsearch";

// 操作 1 影响一个使用 "index" 操作的索引
interface Op1IndexRow {
  index: {
    _index: string;
    _id: string;
    retry_on_conflict: number;
  }
}

interface Op1BulkDocument {
  a: string,
}

type Op1BulkBody = Array<Op1BulkDocument | Op1IndexRow>;


interface Op2IndexRow {
  index: {
    _index: string;
    _id: string;
    retry_on_conflict: number;
  }
}

interface Op2BulkDocument {
  b: string,
}

type Op2BulkBody = Array<Op2BulkDocument | Op2IndexRow>;

const client = new Client({
  node: 'localhost'
})

const bulkSave = async (operations: Op1BulkBody | Op2BulkBody) => {
  await client.bulk({
    refresh: true,
    operations,
  });
}

我真正不理解的是,我可以通过以下类型使其“typescript友好”:Array<Op1BulkDocument | Op1IndexRow | Op2BulkDocument | Op2IndexRow>

问题是,这个类型对我来说是错误的,因为操作要么是 Op1BulkDocument | Op1IndexRow,要么是 Op2BulkDocument | Op2IndexRow,但从不同时。

英文:

Using:

  • NodeJS v16.16.0
  • "@elastic/elasticsearch": "8.7.0",

I want to create a function that will accept multiple kind of bulk operations.
The goal for me is to ensure the input of this functions will affect my index with good values (here a or b).

Here is the code snippet that i cannot correctly type:

import { Client } from &quot;@elastic/elasticsearch&quot;;

// Operation 1 affect 1 index with &quot;index&quot; action
interface Op1IndexRow {
  index: {
    _index: string;
    _id: string;
    retry_on_conflict: number;
  }
}

interface Op1BulkDocument {
  a: string,
}

type Op1BulkBody = Array&lt;Op1BulkDocument | Op1IndexRow&gt;;


interface Op2IndexRow {
  index: {
    _index: string;
    _id: string;
    retry_on_conflict: number;
  }
}

interface Op2BulkDocument {
  b: string,
}

type Op2BulkBody = Array&lt;Op2BulkDocument | Op2IndexRow&gt;;

const client = new Client({
  node: &#39;localhost&#39;
})

const bulkSave = async (operations: Op1BulkBody | Op2BulkBody) =&gt; {
  await client.bulk({
    refresh: true,
    operations,
  });
}

The thing I really don't understand is that i can make it "typescript friendly" with the following type: Array&lt;Op1BulkDocument | Op1IndexRow | Op2BulkDocument | Op2IndexRow&gt;.

The problem is that this type is wrong for me because the operations is either Op1BulkDocument | Op1IndexRow either Op2BulkDocument | Op2IndexRow but never both at the same time.

答案1

得分: 0

提供的代码几乎实现了你想要的。例如,它不允许你混合使用 Op1BulkDocumentOp2BulkDocument

declare const op1doc: Op1BulkDocument;
declare const op2doc: Op2BulkDocument;
bulkSave([op1doc, op2doc]);

> 类型“(Op1BulkDocument | Op2BulkDocument)[]”的参数不能赋给类型“Op1BulkBody | Op2BulkBody”的参数。

这是因为 Op1BulkDocument 具有 a 成员,而 Op2BulkDocument 没有。

然而,它允许你混合使用 Op1IndexRowOp2IndexRow

declare const op1index: Op1IndexRow;
declare const op2index: Op2IndexRow;
bulkSave([op1index, op2index]);

为什么呢?错误消息已经给出了提示:Op1IndexRowOp2IndexRow 具有相同的定义。你可以将类型为 Op1IndexRow 的变量分配给类型为 Op2IndexRow 的变量,因为它们具有兼容的定义。

TypeScript 不仅仅关注精确的接口名称,而是检查接口定义是否兼容(是否可以 赋值)。

我建议你使用一个单一的接口 OpIndexRow 而不是两个不同但相同的接口。

英文:

The code you provided almost does what you want. For example, it does not allow you to mix Op1BulkDocument with Op2BulkDocument:

declare const op1doc: Op1BulkDocument;
declare const op2doc: Op2BulkDocument;
bulkSave([op1doc, op2doc]);

> Argument of type '(Op1BulkDocument | Op2BulkDocument)[]' is not assignable to parameter of type 'Op1BulkBody | Op2BulkBody'.

That is because Op1BulkDocument has a member a which Op2BulkDocument does not have.

However it does allow you to mix Op1IndexRow with Op2IndexRow:

declare const op1index: Op1IndexRow;
declare const op2index: Op2IndexRow;
bulkSave([op1index, op2index]);

Why? The error message already gives you a hint: Op1IndexRow en Op2IndexRow have the same definition. You can assign a variable of type Op1IndexRow to a variable op type Op2IndexRow, because they have the compatible definitions.

TypeScript does not look at the exact interface name but checks if the interface definition is the compatible (is assignable).

I suggest you use a single interface OpIndexRow instead of two different (but the same) interfaces.

huangapple
  • 本文由 发表于 2023年4月17日 20:35:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76035220.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定