ChatGPT解决这个技术问题 Extra ChatGPT

索引签名参数类型不能是联合类型。考虑改用映射对象类型

我正在尝试使用以下模式:

enum Option {
  ONE = 'one',
  TWO = 'two',
  THREE = 'three'
}

interface OptionRequirement {
  someBool: boolean;
  someString: string;
}

interface OptionRequirements {
  [key: Option]: OptionRequirement;
}

这对我来说似乎很简单,但是我收到以下错误:

索引签名参数类型不能是联合类型。请考虑改用映射对象类型。

我究竟做错了什么?

key 的类型只能是字符串、数字或符号。枚举不是。

j
jcalz

您可以使用 TS "in" 运算符并执行以下操作:

enum Options {
  ONE = 'one',
  TWO = 'two',
  THREE = 'three',
}
interface OptionRequirement {
  someBool: boolean;
  someString: string;
}
type OptionRequirements = {
  [key in Options]: OptionRequirement; // Note that "key in".
}

呃,这不编译? TypeScript playground says:“接口中的计算属性名称必须引用类型为文字类型或‘唯一符号’类型的表达式。”
interface OptionRequirements 更改为 type OptionRequirements
这实际上对我不起作用:接口中的计算属性名称必须引用其类型为文字类型或“唯一符号”类型的表达式
我已编辑此答案以使用映射类型别名而不是接口。原始答案不能在我见过的任何 TypeScript 版本下编译,当然也不能在当前版本的 TypeScript(截至 2020 年 8 月的 4.0)下编译。 @NachoJusticiaRamos,如果您可以证明您的原始版本实际上可以在某个版本的 TypeScript 中工作,那么我很乐意恢复编辑,以及您需要使用的环境的描述以使其工作。干杯!
有人可以解释一下这里发生了什么吗? TS 在将枚举变量设置为键时遇到的潜在问题是什么?为什么将“界面”更改为“类型”可以解决问题?
u
unional

最简单的解决方案是使用 Record

type OptionRequirements = Record<Options, OptionRequirement>

你也可以自己实现它:

type OptionRequirements = {
  [key in Options]: OptionRequirement;
}

此构造仅适用于 type,但不适用于 interface

您定义中的问题是说您的接口的键应该是 Options 类型,其中 Options 是枚举,而不是字符串、数字或符号。

key in Options 表示“对于那些在联合类型选项中的特定键”。

type 别名比 interface 更灵活、更强大。

如果您的类型不需要在课堂上使用,请选择 type 而不是 interface


那很酷。现在如果我需要这个变量是未定义的,你以后怎么初始化它?
@KatLimRuiz:[key in Options]: OptionRequirement | undefined
有趣...如果您在 Record 输入中执行类似 keyof Options 的操作,它可以正常工作,但如果您通过“自己实现”路线执行此操作,则会出现语法错误,无法执行 [keyof Options]: OptionRequirement。就我而言,我的 Option 是一种类型,而不是枚举。
另外,我想知道是否有一种方法可以强制密钥在枚举中,而不是让打字稿抱怨你必须彻底使用该枚举的所有成员......
啊,当然...使用 Exclude,您可以限制应在 Record 中实现哪些成员!
A
AmerllicA

就我而言:

export type PossibleKeysType =
  | 'userAgreement'
  | 'privacy'
  | 'people';

interface ProviderProps {
  children: React.ReactNode;
  items: {
    //   ↙ this colon was issue
    [key: PossibleKeysType]: Array<SectionItemsType>;
  };
}

我通过使用 in 运算符而不是使用 : 来修复它

~~~

interface ProviderProps {
  children: React.ReactNode;
  items: {
    //     ↙ use "in" operator
    [key in PossibleKeysType]: Array<SectionItemsType>;
  };
}

I
Igor Kurkov

我有一些类似的问题,但我的情况是接口中的另一个字段属性,所以我的解决方案作为一个示例,带有可选字段属性和键的枚举:

export enum ACTION_INSTANCE_KEY {
  cat = 'cat',
  dog = 'dog',
  cow = 'cow',
  book = 'book'
}

type ActionInstances = {
  [key in ACTION_INSTANCE_KEY]?: number; // cat id/dog id/cow id/ etc // <== optional
};

export interface EventAnalyticsAction extends ActionInstances { // <== need to be extended
  marker: EVENT_ANALYTIC_ACTION_TYPE; // <== if you wanna add another field to interface
}

S
Stefan

不使用接口,而是使用映射对象类型

enum Option {
  ONE = 'one',
  TWO = 'two',
  THREE = 'three'
}

type OptionKeys = keyof typeof Option;

interface OptionRequirement {
  someBool: boolean;
  someString: string;
}

type OptionRequirements = {                 // note type, not interface
  [key in OptionKeys]: OptionRequirement;   // key in
}

你不需要添加这么多类型,@Nacho Justicia Ramos 的解决方案唯一让一些人忽略的是最后一个类型是 TYPE 而不是 INTERFACE。您可以从该类型创建一个接口。
A
Alazzawi

在我的例子中,我需要这些属性是可选的,所以我创建了这个泛型类型。

type PartialRecord<K extends string | number | symbol, T> = { [P in K]?: T; };

然后像这样使用它:

type MyTypes = 'TYPE_A' | 'TYPE_B' | 'TYPE_C';

interface IContent {
    name: string;
    age: number;
}

interface IExample {
    type: string;
    partials: PartialRecord<MyTypes, IContent>;
}

例子

const example : IExample = {
    type: 'some-type',
    partials: {
        TYPE_A : {
            name: 'name',
            age: 30
        },
        TYPE_C : {
            name: 'another name',
            age: 50
        }
    }
}

Q
Questioning

我有一个类似的问题。在创建角度表单验证器时,我试图只使用特定的键。

export enum FormErrorEnum {
  unknown = 'unknown',
  customError = 'customError',
}

export type FormError = keyof typeof FormErrorEnum;

以及用法:

static customFunction(param: number, param2: string): ValidatorFn {
  return (control: AbstractControl): { [key: FormErrorEnum]?: any } => {
    return { customError: {param, param2} };
  };
}

这将允许使用 1 - X 个密钥。


J
Joe

我遇到了类似的问题,我发现这个简单的解决方案对我来说就像一个魅力:只需将 [] 替换为 ():

interface OptionRequirements {
  (key: Option): OptionRequirement;
}

在我的情况下,我需要使用联合类型而不是枚举,但两者都适合我:

type DocumentId = 'invoiceId' | 'orderId';

export interface INote {
    id: number;
    organizationId: number;
    (key: DocumentId): number;
    //...
}