数组类型和普通对象类型的交集是什么?

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

What is the intersection of an array type and a regular object type?

问题

我有一个在TypeScript 5.1.3中的简单片段,我试图弄清楚类型为`unknown[] & A`的对象会是什么样子。

```typescript
interface A {
    text: string
}

type AB = unknown[] & A

let a: AB = [{text: "ASDF"}]

console.log(a)

目前,我得到一个错误,说

类型“{ text: string; }[]”不能分配给类型“AB”。
  在类型“{ text: string; }[]”中缺少属性“text”,但在类型“A”中是必需的。(2322)

有人知道这种类型的对象应该是什么样子吗?


<details>
<summary>英文:</summary>

I have this simple snippet in TypeScript 5.1.3 where I try to figure out what an object of type `unknown[] &amp; A` would look like.

```typescript
interface A {
    text: string
}

type AB = unknown[] &amp; A

let a: AB = [{text: &quot;ASDF&quot;}]

console.log(a)

As it stands, I'm getting an error saying

Type &#39;{ text: string; }[]&#39; is not assignable to type &#39;AB&#39;.
  Property &#39;text&#39; is missing in type &#39;{ text: string; }[]&#39; but required in type &#39;A&#39;.(2322)

Does anyone know what an object of this type is supposed to look like?

答案1

得分: 3

你想知道什么值满足下面所定义的 AB 类型:

interface A {
    text: string
}

type AB = unknown[] & A;

首先,unknown[] 表示一个元素类型未知的数组。A 表示一个具有属性 text 类型为 string 的对象。

AB 类型是通过交叉类型将这两种类型相交而创建的。这创建了一个新类型,可以分配给交叉类型的两个类型:它是满足这两种类型的值集合的交集。
因此,满足这个类型的值是一个具有额外属性 text 类型为 string 的数组。

这可以通过以下类型安全的方式创建:

interface A {
  text: string
}

type AB = unknown[] & A

const arr = [1, 2, 3]

const result: AB = Object.assign(arr, { text: "Some text" })

TS Playground

顺便说一下...
如果你想知道如何创建一个类型,它与数组的 元素 类型与给定目标类型相交,你可以使用以下泛型类型。它接受一个数组类型,并生成一个新的数组类型,其元素类型与给定目标类型相交。
也就是说,你可以用它将 { name: string }[]{ text: string } 转化为 { name: string; text: string }[]

interface A {
  text: string
}

type MyArray = { name: string }[]

type IntersectArrayElements<A, T> = A extends (infer Element)[]
  ? (Element & T)[]
  : never

type IntersectedArray = IntersectArrayElements<MyArray, A>
//   ^? ({ name: string; } & A)[]
//    = { name: string; text: string; }[]

TS Playground

英文:

You want to know what value satisfies AB as defined below:

interface A {
    text: string
}

type AB = unknown[] &amp; A;

First of all, unknown[] represents an array of elements of unknown type. A represents an object with the property text of type string.

AB is created by intersecting these types.
This creates a new type that is assignable to both of the intersected types: it is the intersection of the sets of values that satisfy those types.
Therefore, the value that satisfies this type is an array with the extra property text of type string.

This can be created in a type-safe way like follows:

interface A {
  text: string
}

type AB = unknown[] &amp; A

const arr = [1, 2, 3]

const result: AB = Object.assign(arr, { text: &quot;Some text&quot; })

TS Playground

On a side note...
If you want to know how to create a type that has the "target" type intersected with the element type of the array, you can use the following generic type. It takes an array type and produces a new array type with the element type intersected with a given target type.
I.e., you can use it to turn { name: string }[] and { text: string } into { name: string; text: string}[].

interface A {
  text: string
}

type MyArray = { name: string }[]

type IntersectArrayElements&lt;A, T&gt; = A extends (infer Element)[]
  ? (Element &amp; T)[]
  : never

type IntersectedArray = IntersectArrayElements&lt;MyArray, A&gt;
//   ^? ({ name: string; } &amp; A)[]
//    = { name: string; text: string; }[]

TS Playground

答案2

得分: 0

我认为答案在于 A 不能限制来自 unknown[] 的字段。text 字段不在 TypeScript 数组中,因此它实际上不能被交叉。

目前,没有对象可以是类型 AB,但如果 A 扩展空对象 {} 或者是另一种类型的数组(例如 type A = {text: string}[]),这将可以正常工作。

英文:

I think the answer lies in the fact that A needs to not constrain fields from unknown[]. The text field isn't in the TypeScript array, so it can't really be intersected.

As it stands, no object can be of type AB, but if A were to extend the empty object {} or be another type of array (e.g. type A = {text: string}[]) this would work fine.

huangapple
  • 本文由 发表于 2023年6月29日 02:33:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76575841.html
匿名

发表评论

匿名网友

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

确定