You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular编辑项时出现“Property ... does not exist on type”错误求助

问题分析

你遇到的"Property ... does not exist on type"错误,核心原因有三个:

  • 表单结构设计错误,顶层FormGroup中定义的read/write/delete等控件,和模板中每个模块独立的权限字段不匹配
  • 在ngOnInit中错误地直接访问数组data1.actions的属性(比如data1.actions.id),但actions是AllModules[]类型,数组本身没有这些属性
  • 模板中混合使用ngModel和formControlName,且绑定的控件不存在于当前FormGroup中
解决方案

1. 重构表单结构,用FormArray处理多模块权限

每个模块都有独立的权限字段,需要用FormArray管理动态表单控件,替代顶层单个控件:

constructor(...) {
  this.form = this._formBuilder.group({
    id: [null],
    name: [null, Validators.required],
    branches: [null, Validators.required],
    // 用FormArray存储每个模块的权限组
    modulesPermissions: this._formBuilder.array([])
  })
}

// 辅助方法:创建单个模块的权限表单组
private createModulePermissionGroup(module: AllModules): FormGroup {
  return this._formBuilder.group({
    moduleId: [module.id],
    read: [module.read ?? false],
    write: [module.write ?? false],
    delete: [module.delete ?? false]
  })
}

在获取模块数据后初始化FormArray:

seeMeModules() {
  this.selectedModule = this.serviceGroup.getAllModule().subscribe(
    resp => {
      this.selectedAllModules = resp;
      const permissionsArray = this.form.get('modulesPermissions') as FormArray;
      permissionsArray.clear();
      // 为每个模块添加权限表单组
      this.selectedAllModules.forEach(module => {
        permissionsArray.push(this.createModulePermissionGroup(module));
      });

      this.allCategories = this.filterGetAllCategories(resp)
    });
}

2. 修复ngOnInit中的表单赋值逻辑

data1.actions是数组,需遍历匹配模块后更新对应表单控件:

ngOnInit(): void {
  this.seeMeBranch();
  this.seeMeModules();

  const data1: GrupoSegurancaInterface = this.route.snapshot.data['element'];
  // 赋值基础字段
  this.form.patchValue({
    id: data1.id,
    name: data1.name,
    branches: data1.branches.id
  });

  // 等待模块数据加载后同步权限
  this.selectedModule.add(() => {
    const permissionsArray = this.form.get('modulesPermissions') as FormArray;
    data1.actions.forEach(action => {
      const groupIndex = permissionsArray.controls.findIndex(
        ctrl => ctrl.get('moduleId')?.value === action.id
      );
      if (groupIndex !== -1) {
        permissionsArray.at(groupIndex).patchValue({
          read: action.read,
          write: action.write,
          delete: action.delete
        });
      }
    });
  });
}

3. 修改模板,正确绑定FormArray控件

去掉错误的ngModel和顶层formControlName,改用formArrayName和formGroupName绑定:

<mat-tab label="Permissões">
  <section>
    <h4>Modulos do Grupo de Segurança</h4>
    <hr />
    <form [formGroup]="form">
      <!-- 绑定modulesPermissions FormArray -->
      <div formArrayName="modulesPermissions">
        <div *ngFor="let category of allCategories" class="modulecheckbox">
          <h4>{{ category.description }}</h4>
          <div class="checkboxpermissions">
            <mat-checkbox
              *ngFor="
                let module of filterItemsByCategory(selectedAllModules, category);
                let i = index
              "
              [value]="module.id.toString()"
            >
              {{ module.name }}
              <!-- 绑定对应索引的权限表单组 -->
              <div class="checkboxoptions" [formGroupName]="i">
                <mat-checkbox formControlName="read">Leitura</mat-checkbox>
                <mat-checkbox formControlName="write">Escrita</mat-checkbox>
                <mat-checkbox formControlName="delete">Exclusão</mat-checkbox>
              </div>
            </mat-checkbox>
          </div>
        </div>
      </div>
    </form>
  </section>
  <hr />
</mat-tab>

4. 修复onSubmit中的数据组装逻辑

从FormArray中读取权限数据,确保和接口格式匹配:

onSubmit(){
  const formValue = this.form.value;
  const permissionsArray = this.form.get('modulesPermissions') as FormArray;
  
  let data = {
    "id": formValue.id,
    "name": formValue.name,
    "branches": this.branchesControl.value.map((element:any) =>{
      return { "id" : element }
    }),
    "actions": permissionsArray.controls.map(ctrl => {
      const ctrlValue = ctrl.value;
      return {
        "module":{ "id": ctrlValue.moduleId },
        "read": ctrlValue.read,
        "write": ctrlValue.write,
        "delete": ctrlValue.delete
      }
    })
  }

  this.serviceGroup.save(data).subscribe(result => this.onSucess(), erro => this.onError() );
}

额外类型安全优化

  • 修正selectedAllBranches的类型:
selectedAllBranches: Branches[] = [];
  • 优化idsToToppings方法的类型定义:
idsToToppings(ids: number[]): string[] {
  return this.selectedAllBranches
    .filter(t => ids.includes(t.id))
    .map(element => element.name);
}
关键错误总结
  1. 混淆数组类型和单个元素类型:data1.actions是数组,不能直接访问id/read等属性,必须遍历操作单个元素
  2. 表单结构与数据结构不匹配:多模块权限需用FormArray管理,而非顶层单个控件
  3. 模板错误绑定不存在的表单控件,触发TypeScript类型检查报错

内容的提问来源于stack exchange,提问作者Jeferson Carlos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 12:22:04