类型“MonoTypeOperatorFunction<T>”的参数不可分配给类型“OperatorFunction<T |”的参数 未定义,T>'

sha*_*aka 2 generics firebase angular

我正在尝试制作通用 Firestore 服务。这是我的脚本,

doc$(id: string): Observable<T> {
return this.firestore.doc<T>(`${this.basePath}/${id}`).valueChanges().pipe(
  tap(r => {
    if (!environment.production) {
      console.groupCollapsed(`Firestore Streaming [${this.basePath}] [doc$] ${id}`);
      console.log(r);
      console.groupEnd();
    }
  }),
 );
}
Run Code Online (Sandbox Code Playgroud)

警告弹出窗口为,

“MonoTypeOperatorFunction”类型的参数不可分配给“OperatorFunction<T | ”类型的参数 未定义,T>'。

在此输入图像描述

这是我的完整代码,

import {Inject, Injectable} from '@angular/core';
import {AngularFirestore, QueryFn} from '@angular/fire/firestore';
import {Observable} from 'rxjs';
import {tap} from 'rxjs/operators';
import { environment } from 'src/environments/environment';

@Injectable({
  providedIn: 'root'
})
export abstract class FirestoreService<T> {

  protected abstract basePath: string;

  constructor(
    @Inject(AngularFirestore) protected firestore: AngularFirestore,
  ) {
  }

  doc$(id: string): Observable<T> {
    return this.firestore.doc<T> 
    (`${this.basePath}/${id}`).valueChanges().pipe(
       tap(r => {
            if (!environment.production) {
                  console.groupCollapsed(`Firestore Streaming 
                     [${this.basePath}] [doc$] ${id}`);
            console.log(r);
            console.groupEnd();
       }
     }),
    );
   }

   collection$(queryFn?: QueryFn): Observable<T[]> {
     return this.firestore.collection<T>(`${this.basePath}`, 
         queryFn).valueChanges().pipe(
           tap(r => {
             if (!environment.production) {
                  console.groupCollapsed(`Firestore Streaming 
                   [${this.basePath}] [collection$]`);
                  console.table(r);
                  console.groupEnd();
             }
         }),
     );
   }

  create(value: T) {
     const id = this.firestore.createId();
     return this.collection.doc(id).set(Object.assign({}, { id }, 
          value)).then(_ => {
                if (!environment.production) {
                     console.groupCollapsed(`Firestore Service 
                        [${this.basePath}] [create]`);
                     console.log('[Id]', id, value);
                     console.groupEnd();
                }
          });
     }

  delete(id: string) {
      return this.collection.doc(id).delete().then(_ => {
         if (!environment.production) {
             console.groupCollapsed(`Firestore Service [${this.basePath}] 
                 [delete]`);
             console.log('[Id]', id);
             console.groupEnd();
         }
      });
 }

 private get collection() {
        return this.firestore.collection(`${this.basePath}`);
 }
}
Run Code Online (Sandbox Code Playgroud)

package.json 文件:

{
   "name": "adm-management",
   "version": "0.0.0",
   "scripts": {
      "ng": "ng",
      "start": "ng serve",
      "build": "ng build",
      "test": "ng test",
      "lint": "ng lint",
      "e2e": "ng e2e"
 },
 "private": true,
 "dependencies": {
    "@angular/animations": "~11.0.0",
    "@angular/cdk": "^11.0.1",
    "@angular/common": "~11.0.0",
    "@angular/compiler": "~11.0.0",
    "@angular/core": "~11.0.0",
    "@angular/fire": "^6.1.4",
    "@angular/forms": "~11.0.0",
    "@angular/material": "^11.0.1",
    "@angular/platform-browser": "~11.0.0",
    "@angular/platform-browser-dynamic": "~11.0.0",
    "@angular/router": "~11.0.0",
    "@fortawesome/angular-fontawesome": "^0.8.0",
    "@fortawesome/fontawesome-svg-core": "^1.2.32",
    "@fortawesome/free-brands-svg-icons": "^5.15.1",
    "@fortawesome/free-regular-svg-icons": "^5.15.1",
    "@fortawesome/free-solid-svg-icons": "^5.15.1",
    "rxjs": "~6.6.0",
    "tslib": "^2.0.0",
    "zone.js": "~0.10.2",
    "firebase": "^7.0 || ^8.0"
 },
 "devDependencies": {
    "@angular-devkit/build-angular": "~0.1100.0",
    "@angular/cli": "~11.0.0",
    "@angular/compiler-cli": "~11.0.0",
    "@types/jasmine": "~3.6.0",
    "@types/node": "^12.11.1",
    "codelyzer": "^6.0.0",
    "jasmine-core": "~3.6.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "~5.1.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.0.3",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "protractor": "~7.0.0",
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0",
    "typescript": "~4.0.2",
    "@angular-devkit/architect": ">= 0.900 < 0.1200",
    "firebase-tools": "^8.0.0",
    "fuzzy": "^0.1.3",
    "inquirer": "^6.2.2",
    "inquirer-autocomplete-prompt": "^1.0.1",
    "open": "^7.0.3"
  }
}
Run Code Online (Sandbox Code Playgroud)

有什么解决办法吗?

(这是我提到的链接 - https://www.toptal.com/angular/state-management-in-angular-using-firebase

tmh*_*005 5

看来我已经知道你的问题来自哪里了。问题在于valueChanges返回的方法,其中Observable<T | undefined>包含.undefinedT

为了修复它,您可以:

  • 通过将其设置为禁用strict模式tsconfig.jsonfalse

  • 或将您的代码转换为Observable<T>如下所示:

doc$(id: string): Observable<T> {
    // Cast back to `Observable<T>` to compatible with `tap`'s return
    const obs = this.firestore.doc<T>(`${this.basePath}/${id}`).valueChanges() as Observable<T>;
    
    return obs.pipe(
      tap(r => {
        console.log(r);
        console.groupEnd();
      }),
    );
}
Run Code Online (Sandbox Code Playgroud)