在我使用最新版本的同时,按照Angular 4中的课程进行操作,我一生无法解决这个问题。
尝试过滤产品时,我在products.component.ts
中遇到错误。
任何帮助将不胜感激,我仍然很新,这是我学习Angular的第四天。
Type 'unknown[]' is not assignable to type 'Product[]'.
Type '{}' is missing the following properties from type 'Product': title, price, category, imageUrl
product.ts
export interface Product {
title: string;
price: number;
category: string;
imageUrl: string;
}
product.service.ts
import { map } from 'rxjs/operators';
import { AngularFireDatabase } from 'angularfire2/database';
import { Injectable } from '@angular/core';
import { Product } from './models/product';
@Injectable({
providedIn: 'root'
})
export class ProductService {
constructor(private db: AngularFireDatabase) { }
create(product) {
return this.db.list('/products').push(product);
}
getAll(){
return this.db.list('/products').snapshotChanges()
.pipe(
map(actions =>
actions.map(a => ({ key: a.key, ...a.payload.val() }))
)
);
}
get(productId) {
return this.db.object('/products/' + productId);
}
update(productId, product) {
return this.db.object('/products/' + productId).update(product);
}
delete(productId)
{
return this.db.object('/products/' + productId).remove();
}
}
products.component.ts
import { ActivatedRoute } from '@angular/router';
import { CategoryService } from './../category.service';
import { ProductService } from './../product.service';
import { Component, OnInit } from '@angular/core';
import { Product } from '../models/product';
import { Observable } from 'rxjs';
@Component({
selector: 'app-products',
templateUrl: './products.component.html',
styleUrls: ['./products.component.css']
})
export class ProductsComponent {
products: Product[];
categories$: Observable<any[]>;
category: string;
filteredProducts: Product[];
constructor(
productService: ProductService,
categoryService: CategoryService,
route : ActivatedRoute) {
productService.getAll().subscribe(a => this.products = a); //error on this.products:
//"Type 'unknown[]' is not assignable to type 'Product[]'."
// "Type '{}' is missing the following properties from type 'Product': title, price, category, imageUrl"
this.categories$ = categoryService.getAll();
route.queryParamMap.subscribe(params => {
this.category = params.get('category');
this.filteredProducts = (this.category) ?
this.products.filter(p => p.category === this.category) : this.products;
});
}
}
答案 0 :(得分:0)
我相信这是因为您没有指定将使用getAll()方法检索的数据类型。
TypeScript是一种强类型语言,因此它尝试在编译时验证所有类型和赋值。
尝试使用以下方法更改不稳定线:
productService.getAll().subscribe((a: Product[]) => this.products = a);
答案 1 :(得分:0)
问题在于这个可观察的-
getAll(){
return this.db.list('/products').snapshotChanges()
.pipe(
map(actions =>
actions.map(a => ({ key: a.key, ...a.payload.val() }))
)
);
}
您正在将动作数组映射到Array <{key,[]}>。 当您期望一个数组(即Product [])时。
因此,请确保将操作数组映射到产品数组(即数组) 尝试像这样更改代码-
getAll(){
return this.db.list('/products').snapshotChanges()
.pipe(
map(actions =>
actions.map(a => {
title: <fill this from equivalent in a>,
price: <fill this from equivalent in a>,
category: <fill this from equivalent in a>,
imageUrl: <fill this from equivalent in a>
})
)
);
}
顺便说一句,问题不在Angular 4和Angular 8中[同一示例在Angular8中也会产生相同的错误]。这就是Typescript类型检查的工作方式。如果您将用普通的javascript编写相同的代码,则可能在编译时没有看到任何错误,但在运行时会看到意外的行为。这里的打字稿可以确保在编译时尽可能地捕获错误。
答案 2 :(得分:0)
product.ts
export interface Product {
key: string;
title: string;
price: number;
category: string;
imageUrl: string;
}
products.component.ts
import { ProductService } from './../../product.service';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { Product } from 'src/app/models/product';
@Component({
selector: 'app-admin-products',
templateUrl: './admin-products.component.html',
styleUrls: [ './admin-products.component.css' ]
})
export class AdminProductsComponent implements OnInit, OnDestroy {
products: Product[];
filteredProducts: Product[];
subscription: Subscription;
constructor(private productservice: ProductService) {
this.subscription = this.productservice
.getAll()
.subscribe((products: Product[]) => (this.filteredProducts = this.products = products));
}
filter(query: string) {
this.filteredProducts = query
? this.products.filter((p) => p.title.toLowerCase().includes(query.toLowerCase()))
: this.products;
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
ngOnInit() {}
}
products.component.html
<tr *ngFor="let p of filteredProducts">
<td>{{ p.title }}</td>
<td>{{ p.price }}</td>
<td>
<a [routerLink]="['/admin/admin-products/', p.key]">Edit</a>
</td>
</tr>
答案 3 :(得分:0)
AFAIK list
是通用名称,您可以并且应该提供键入内容。代替
return this.db.list('/products').snapshotChanges()
做
return this.db.list<Product>('/products').snapshotChanges()
https://github.com/angular/angularfire2/blob/master/docs/rtdb/lists.md
答案 4 :(得分:0)
这可以改变你的生活。
getAll() {
return this.db.list<Product>('/products').snapshotChanges()
.pipe(
map(actions =>
actions.map(a => ({ key: a.key, ...a.payload.val() }))
)
);
}