gpt4 book ai didi

typescript - 强制 Typescript 对象只有一组中的一个键

转载 作者:行者123 更新时间:2023-12-04 15:32:36 25 4
gpt4 key购买 nike

基本问题和背景

我正在尝试键入一组对象,其中每个对象都有一组中的一个键。例如:

const foo = [
{ a: 'foo' },
{ b: 'bar' },
{ c: 'baz' },
]

我的第一次尝试是 key in一个工会:

type Foo = { [key in 'a' | 'b' | 'c']: string }[]
const foo: Foo = [
{ a: 'foo' },
{ b: 'bar' },
{ c: 'baz' },
]

这不起作用,因为 Typescript 希望每个对象都拥有联合中的所有键:

type Foo = { [key in 'a' | 'b' | 'c']: string }[]
const foo: Foo = [
{ a: 'foo', b: 'bar', c: 'baz' },
{ a: 'foo', b: 'bar', c: 'baz' },
{ a: 'foo', b: 'bar', c: 'baz' },
]

我的第二次尝试是:

type A = { a: string }
type B = { b: string }
type C = { c: string }
type Foo = (A | B | C)[]
const foo: Foo = [
{ a: 'foo' },
{ b: 'bar' },
{ c: 'baz' },
]

但是,作为 jcalz points out ,这仍然允许:

const foo: Foo = [{ a: 'foo', b: 'bar' }]

有没有办法强制每个对象只有一个键,并且该键是 abc ?

稍微多一点的上下文

我们的项目正在尝试读取 this JSON在 React 中处理不同国家地址字段的动态表单。当 Typescript 读取该 JSON blob 时,它会出错。最重要的是,它认为 fields键并不总是一个数组,所以不让我 .map超过它。所以我决定将 JSON blob 复制到我们的项目中并手动输入。我试图捕捉 fields 的事实数组是一个对象数组,要么是 thoroughfare , premise , 或 locality还有那个 locality是一个对象数组,要么是 localityname , 等等。

最佳答案

如果您想要一种类型只需要一个键,您可以(大多数情况下)将其表示为对象类型的联合,其中联合的每个成员都定义了一个键,而所有其余的键都定义为可选和未定义(这是最接近的)你可以在 TypeScript 中说一个键是 missing )。所以你的 Foo应该看起来像:

type Foo = Array<
{ a: string; b?: undefined; c?: undefined; } |
{ a?: undefined; b: string; c?: undefined; } |
{ a?: undefined; b?: undefined; c: string; }
>

我们如何以编程方式获得它或类似的东西?好吧,解释起来有点棘手,但我的解决方案如下所示:
type ExactlyOneKey<K extends keyof any, V, KK extends keyof any = K> =
{ [P in K]: { [Q in P]: V } &
{ [Q in Exclude<KK, P>]?: undefined } extends infer O ?
{ [Q in keyof O]: O[Q] } : never
}[K];

type Foo = Array<ExactlyOneKey<"a" | "b" | "c", string>>;

型号 ExactlyOneKey<K, V>拿 key 工会 K并对其进行迭代。每个成员(member) P在联合中,它创建一个对象类型,该对象类型存在该键而其他键不存在/缺失。型号 {[Q in P]: V} (又名 Record<P, V> )具有当前键和值,以及类型 {[Q in Exclude<KK, P>]?: undefined}将所有其余的键作为可选和未定义的。我们将它们与 & 相交获得具有这两种功能的类型。然后我在 ... extends infer O ? { [Q in keyof O]: O[Q] } : never处做了个小 Action 将采用类型 ...并将所有交叉点合并为一个对象类型。这不是绝对必要的,但它会改变 {a: string} & {b?: undefined, c?: undefined}{a: string; b?: undefined; c?: undefined;}这更可口。

让我们确保它有效:
const foo: Foo = [
{ a: 'foo' },
{ b: 'bar' },
{ c: 'baz' },
]; // okay

const badFoo: Foo = [
{ d: "nope" }, // error
{ a: "okay", b: "oops" } // error
];

看起来挺好的。好的,希望有帮助;祝你好运!

Playground link to code

关于typescript - 强制 Typescript 对象只有一组中的一个键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60872063/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com