【问题标题】:typescript Property 'options' does not exist on type of Union type联合类型的类型上不存在 typescript 属性“选项”
【发布时间】:2019-01-20 13:03:23
【问题描述】:

我有几个接口和一个联合类型:

export interface FieldOptions {
  value: string | number;
  viewValue: string;
}

export interface BaseField {
  id: string;
  derived?: boolean;
  required?: boolean;
}

export interface NumberField extends BaseField {
  type: 'number';
  decimals: number;
}
export interface SelectField extends BaseField {
  type: 'select' | 'select-multi';
  options: FieldOptions[];
  source?: string;
}

export type Field = NumberField | SelectField;

据我了解,当我使用联合类型字段时,它的主要字段可以是数字或选择。

有了这些知识,我的 Angular 组件中有一个函数

getField( key: string ): Field {
  return this.fields.filter( el => el.id === key )[ 0 ];
}

getFieldVersion2( key: string ): any {
  const field = this.fields.filter( el => el.id === key )[ 0 ];
  if ( (<SelectField>field).options ) {
    return field as SelectField;
  } else {
    return field as Field;
  }
}

仅使用在我的模板中调用的函数getField 来获取字段对象,在本例中为带有视图/视图值的选项数组的选择,我在 TS 上收到构建错误:

Property 'options' does not exist on type 'Field'.
   Property 'options' does not exist on type 'NumberField'.

据我了解,Field 是 Number 或 Select 的联合类型。其中一个有options 属性,另一个没有。

所以我创建了getFieldVersion2,希望能解决这个问题。但是,除非我将 any 添加为我的函数的结果类型,否则它将触发构建错误。

使用options的模板触发编译错误:

<mat-form-field  class="input">
  <mat-select formControlName="state">
    <mat-option *ngFor="let option of getField( 'state' ).options" [value]="option.value">
       {{option.viewValue}}
    </mat-option>
  </mat-select>
</mat-form-field>

发生了什么,我应该做些什么更好?

【问题讨论】:

  • 似乎您遇到的错误是尝试实际使用 getField 并可能读取可能存在或不存在的 options 属性的代码;您也可以发布该代码吗? getFieldVersion2 在运行时与 getField 并没有什么不同,因为您在示例中声明的所有 TypeScript 类型在编译为 JavaScript 时都会消失。
  • 完全正确。但是在 typescript 的编译期间,编译器对getFieldVerstion2 很满意。我将修改我的问题并添加模板代码

标签: angular typescript union-types


【解决方案1】:

您创建的界面没有“选项”属性。然后将“字段”类型设置为等于该接口(或可能等于另一个具有“选项”属性的接口)。

然后您尝试调用可能存在或不存在的“选项”属性。这就是编译时收到 ts 错误的原因。

将返回类型切换为“any”是可行的,因为编译器不会尝试猜测您返回的对象的类型(因此“options”可能是一个有效的属性,因此不应抛出错误)。

如果你要调用“Field”类型的“options”属性,你应该在尝试编译你的ts脚本之前确保它存在。

也许将您的方法更新为“getSelectField”和“getNumberField”会是一个更好的选择......但当然有多种方法可以处理这个问题。

【讨论】:

  • 我在getFieldVersion2 中所做的不是一种类型检查并返回正确接口的形式吗?除非我从该函数返回any,否则它仍然不起作用
  • 好吧,我确实意识到 getField 函数仅用于带有选项的字段,因此我可以使其更具体,并将其称为 getOptionsField,它返回一种 SelectField(或稍后RadioField 或 SelectField 的联合类型)。看到模板中的 TS 错误,我有点好奇。
猜你喜欢
  • 1970-01-01
  • 2023-01-19
  • 2020-09-27
  • 2021-02-25
  • 2023-04-02
  • 2018-08-17
  • 1970-01-01
  • 2023-02-06
  • 1970-01-01
相关资源
最近更新 更多