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

Angular项目ng build --prod报属性不存在错误,ng serve正常

解决Angular生产构建时"Property does not exist on type '{}'"的问题

嘿,我明白你现在的困境——开发环境跑的好好的,一到生产构建就炸一堆类型错误,还没法部署。这个问题其实是Angular生产模式下的严格类型检查在搞事情,咱们一步步来搞定它:

问题根源分析

你初始化recipe = {}的时候,TypeScript会自动把它的类型推断成{}(空对象)。生产构建时,TypeScript会开启严格模式,它会较真:空对象上根本没有title、source这些属性啊!所以就抛出了那些错误。但如果你只写recipe;,它的类型会变成undefined或者any,当数据库数据还没加载完时,模板访问recipe.title就会因为recipe是undefined而报错,导致下拉框空白、控制台一堆问题。

完美解决方案:给Recipe定义类型并合理初始化

咱们需要给recipe一个明确的类型,同时初始化必要的属性,两边的问题就都解决了:

  1. 先定义Recipe接口
    在组件文件顶部,添加一个接口来描述你的recipe对象结构,用可选属性(?)允许属性初始为空:
interface Recipe {
  title?: string;
  source?: string;
  category?: string;
  ingredientsList?: { ingredients: string[] };
  directions?: string;
  // 这里可以补充你的recipe对象需要的其他属性
}
  1. 修改recipe的声明和初始化
    把原来的recipe = {};改成下面这样,既指定类型,又初始化ingredientsList避免模板访问时的undefined错误:
recipe: Recipe = {
  ingredientsList: { ingredients: [] }
};
  1. 修改后的完整组件代码
import { RecipeService } from './../recipe.service';
import { Observable } from 'rxjs/Observable';
import { CategoryService } from './../category.service';
import { Component } from '@angular/core';
import { AngularFireObject, AngularFireDatabase, AngularFireList } from 'angularfire2/database';
import { FirebaseListObservable } from "angularfire2/database-deprecated";
import { FormGroup, FormControl, FormArray } from '@angular/forms';
import { FirebaseApp } from 'angularfire2';
import { Router, ActivatedRoute } from '@angular/router';
import 'rxjs/add/operator/take';

// 定义Recipe接口,明确对象结构
interface Recipe {
  title?: string;
  source?: string;
  category?: string;
  ingredientsList?: { ingredients: string[] };
  directions?: string;
}

@Component({
  selector: 'app-recipe-form',
  templateUrl: './recipe-form.component.html',
  styleUrls: ['./recipe-form.component.css']
})
export class RecipeFormComponent {
  categories$: Observable<any>;
  // 用接口类型声明,并初始化必要属性
  recipe: Recipe = {
    ingredientsList: { ingredients: [] }
  };
  id;
  form = new FormGroup({
    ingredients: new FormArray([])
  });

  constructor(
    private categoryService: CategoryService,
    private recipeService: RecipeService,
    private router: Router,
    private route: ActivatedRoute) {
    this.categories$ = categoryService.getCategories();
    this.id = this.route.snapshot.paramMap.get('id');
    if(this.id) 
      this.recipeService.get(this.id).take(1).subscribe(r => this.recipe = r);
  }

  save(recipe){
    recipe.ingredientsList = this.form.value;
    if(this.id) 
      this.recipeService.update(this.id, recipe);
    else 
      this.recipeService.create(recipe);
    this.router.navigate(['/recipes']);
  }

  addIngredient(ingredient: HTMLInputElement) {
    this.ingredients.push(new FormControl(ingredient.value));
    ingredient.value = '';
  }

  getList(){
    return this.form.get('ingredients') as FormArray;
  }

  get ingredients() {
    return this.form.get('ingredients') as FormArray;
  }

  removeIngredient(ingredient: FormControl){
    let index = this.ingredients.controls.indexOf(ingredient);
    this.ingredients.removeAt(index);
  }
}

为什么这能解决问题?

  • 类型安全:有了Recipe接口,TypeScript清楚知道recipe可以拥有哪些属性,生产构建的严格检查就不会再挑刺了。
  • 避免初始化错误:提前给ingredientsList赋值空数组结构,就算数据库数据还没加载完成,模板访问recipe.ingredientsList.ingredients时也不会因为undefined报错,下拉框和表单就能正常显示了。

另外,你的模板里这段代码:

<div *ngIf="recipe.ingredientsList">
  <ul class="list-group">
    <li *ngFor="let i of recipe.ingredientsList.ingredients" (click)="removeIngredient(i)" class="list-group-item">
      {{ i }}
    </li>
  </ul>
</div>

因为我们已经初始化了ingredientsList,*ngIf="recipe.ingredientsList"其实可以去掉,但保留也没问题,多一层安全保障。

现在再跑ng build --prod应该就能顺利完成构建啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:43:20