英文:
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[] & A` would look like.
```typescript
interface A {
text: string
}
type AB = unknown[] & A
let a: AB = [{text: "ASDF"}]
console.log(a)
As it stands, I'm getting an error saying
Type '{ text: string; }[]' is not assignable to type 'AB'.
Property 'text' is missing in type '{ text: string; }[]' but required in type 'A'.(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" })
顺便说一下...
如果你想知道如何创建一个类型,它与数组的 元素 类型与给定目标类型相交,你可以使用以下泛型类型。它接受一个数组类型,并生成一个新的数组类型,其元素类型与给定目标类型相交。
也就是说,你可以用它将 { 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; }[]
英文:
You want to know what value satisfies AB
as defined below:
interface A {
text: string
}
type AB = unknown[] & 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[] & A
const arr = [1, 2, 3]
const result: AB = Object.assign(arr, { text: "Some text" })
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<A, T> = A extends (infer Element)[]
? (Element & T)[]
: never
type IntersectedArray = IntersectArrayElements<MyArray, A>
// ^? ({ name: string; } & A)[]
// = { name: string; text: string; }[]
答案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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论