Typescript 对象数组,每一项都有一个属性

发布于 2025-01-13 08:18:35 字数 1433 浏览 3 评论 0 原文

我正在集成 Google Ads Rest API。我想传递 UserIdentifier 到一个函数,其中每个对象只能有一个项目,因为它是 此 Google Ads API 例如:

f([{hashedEmail: "xxxxxx"}, {hashedPhoneNumber: "xxxxxx"}]) // OK
f([{hashedEmail: "xxxxxx", hashedPhoneNumber: "xxxxxx"}]) // Not Cool

此示例很接近,但我只想使用 Google Ads API 中提到的密钥UserIdentifier 类型。

提前致谢。

I'm integrating Google Ads Rest API.I want to pass an array of type UserIdentifier to a function where each object should only have one item only because it is required by this Google Ads API
for example:

f([{hashedEmail: "xxxxxx"}, {hashedPhoneNumber: "xxxxxx"}]) // OK
f([{hashedEmail: "xxxxxx", hashedPhoneNumber: "xxxxxx"}]) // Not Cool

This example comes close but I only want to use the keys that are mentioned in Google Ads API UserIdentifier type.

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

在巴黎塔顶看东京樱花 2025-01-20 08:18:35

看起来您正在寻找的结构是 C 型联合。这意味着您的对象只具有所有列出的属性中的一个属性。可以轻松创建辅助泛型类型来生成此结构:

type CUnion<T extends Record<string, unknown>> = { [K in keyof T]: { [_ in K]: T[K] } & { [K2 in Exclude<keyof T, K>]?: undefined } }[keyof T];

// { ssn: boolean; webauth?: undefined } | { webauth: string; ssn?: undefined }
type UserID = CUnion<{
  ssn: boolean;
  webauth: string;
}>;

const asdf: UserID = {
  ssn: true,
};

const asdf2: UserID = {
  webauth: "hey"
};

// @ts-expect-error This correctly fails.
const asdf3: UserID = {
  ssn: true,
  webauth: "hey"
}

我们需要显式地使其他属性未定义并且可选,因为当您在联合的其他部分中指定不应该出现的属性时,TypeScript 不会出错实际上就在那儿。无论如何,这是调整为使用此解决方案的代码:

type CUnion<T extends Record<string, unknown>> = { [K in keyof T]: { [_ in K]: T[K] } & { [K2 in Exclude<keyof T, K>]?: undefined } }[keyof T];

type UserIdentifier = CUnion<{
  hashedEmail: string,
  hashedPhoneNumber: string,
  mobileId: string,
  thirdPartyUserId: string,
  addressInfo: {
    hashedFirstName: string,
    hashedLastName: string,
    city: string,
    state: string,
    countryCode: string,
    postalCode: string,
    hashedStreetAddress: string
  }
}>;

declare const f: (identifiers: UserIdentifier[]) => void;

f([{ hashedEmail: "xxxxxx" }, { hashedPhoneNumber: "xxxxxx" }]) // OK -- correctly works!
f([{ hashedEmail: "xxxxxx", hashedPhoneNumber: "xxxxxx" }]) // Not Cool -- correctly errors!

TypeScript Playground 链接

It looks like the sort of structure you are looking for is a C-Style Union. This means that you have an object that only has one property present out of all of the listed ones. A helper generic type can easily be created to generate this structure:

type CUnion<T extends Record<string, unknown>> = { [K in keyof T]: { [_ in K]: T[K] } & { [K2 in Exclude<keyof T, K>]?: undefined } }[keyof T];

// { ssn: boolean; webauth?: undefined } | { webauth: string; ssn?: undefined }
type UserID = CUnion<{
  ssn: boolean;
  webauth: string;
}>;

const asdf: UserID = {
  ssn: true,
};

const asdf2: UserID = {
  webauth: "hey"
};

// @ts-expect-error This correctly fails.
const asdf3: UserID = {
  ssn: true,
  webauth: "hey"
}

We need to make the other properties explicitly undefined and optional because TypeScript does not error when you specify properties in other parts of a union when they should not actually be there. Anyways, here is your code adjusted to use this solution:

type CUnion<T extends Record<string, unknown>> = { [K in keyof T]: { [_ in K]: T[K] } & { [K2 in Exclude<keyof T, K>]?: undefined } }[keyof T];

type UserIdentifier = CUnion<{
  hashedEmail: string,
  hashedPhoneNumber: string,
  mobileId: string,
  thirdPartyUserId: string,
  addressInfo: {
    hashedFirstName: string,
    hashedLastName: string,
    city: string,
    state: string,
    countryCode: string,
    postalCode: string,
    hashedStreetAddress: string
  }
}>;

declare const f: (identifiers: UserIdentifier[]) => void;

f([{ hashedEmail: "xxxxxx" }, { hashedPhoneNumber: "xxxxxx" }]) // OK -- correctly works!
f([{ hashedEmail: "xxxxxx", hashedPhoneNumber: "xxxxxx" }]) // Not Cool -- correctly errors!

TypeScript Playground Link

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文