Typescript 根据另一个属性的值使属性可选

Pug*_*azh 3 typescript

我是 Typescript 的新手,我找不到以下场景的任何解决方案。任何建议都会非常有帮助。

我想让该属性options可选 if typeisSHORT_TEXTLONG_TEXT

export interface Question {
  [keyName: string]: any;
  type: QuestionType;
  id: string;
  label: string;
  helpText?: string;
  placeholder?: string;
  value?: string;
  options?: Option[];
  validations?: any;
  required?: boolean;
  priority?: number;
  intent?: Intent[];
}

export type QuestionType =
  | "DROPDOWN"
  | "CHECKBOX"
  | "RADIO"
  | "SHORT_TEXT"
  | "LONG_TEXT";

export interface Option {
  id: string;
  label: string;
  value?: string;
}
Run Code Online (Sandbox Code Playgroud)

Nik*_*fin 5

我相信你正在寻找的是一个“受歧视的联盟”。本质上正如您所描述的那样:特定属性的值可用于缩小联合中的类型,在这种情况下,您需要一种(或多种)类型,其中options property is required, and one type where it is optional.

\n
export type QuestionType =\n  | "DROPDOWN"\n  | "CHECKBOX"\n  | "RADIO"\n  | "SHORT_TEXT"\n  | "LONG_TEXT";\n\nexport interface Option {\n  id: string;\n  label: string;\n  value?: string;\n}\n\nexport interface Intent {};\n\nexport interface BaseQuestion {\n  [keyName: string]: any;\n  type: QuestionType;\n  id: string;\n  label: string;\n  helpText?: string;\n  placeholder?: string;\n  value?: string;\n  validations?: any;\n  required?: boolean;\n  priority?: number;\n  intent?: Intent[];\n}\n\nexport interface TextQuestion extends BaseQuestion {\n    type: "SHORT_TEXT" | "LONG_TEXT";\n    options?: Option[];\n}\n\nexport interface OptionQuestion extends BaseQuestion {\n    type: "DROPDOWN" | "CHECKBOX" | "RADIO";\n    options: Option[];\n}\n\nexport type Question = TextQuestion | OptionQuestion;\n\n\nconst q: Question = {\n    type: "SHORT_TEXT",\n    id: "id_foo",\n    label: "Test Question",\n};\n\n
Run Code Online (Sandbox Code Playgroud)\n

您可以在Typescript Playground中尝试一下:您将看到验证器对该对象没有问题q,即使它没有属性options。但是,如果您将type属性更改q为 be或or"DROPDOWN"以外的其他属性,验证器将引发错误。"SHORT_TEXT""LONG_TEXT"

\n

您还会注意到,如果您q在交互式游乐场中键入,提示会将其转换为 aTextQuestion而不是 a Question,因为类型已缩小。至少在这个例子中,这实际上阻止了您q.type以后更改属性,但请记住,守卫只会在该联合类型已经缩小的块中进行。例如,如果您要循环问题列表,并重新分配类型:

\n
(questions as Question[]).forEach(q => {\n  q.type = "DROPDOWN";\n});\n
Run Code Online (Sandbox Code Playgroud)\n

在这种情况下,Typescript 并未缩小每个对象的类型,并且不会防止您重新分配type.

\n

希望这可以帮助!\xe2\x9c\x8c\xef\xb8\x8f

\n