error TS2339: Property 'takeUntil' does not exist on type 'Observable<Foo>' and other rxjs v.6 errors

Atticus29 picture Atticus29 · Jul 2, 2018 · Viewed 11.8k times · Source

I just recently updated A LOT of packages in my angular project.

Old package.json:

{
  "name": "data-jitsu",
  "version": "0.0.0",
  "license": "MIT",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^5.2.10",
    "@angular/cdk": "^5.2.5",
    "@angular/common": "5.2.7",
    "@angular/compiler": "5.2.7",
    "@angular/core": "5.2.7",
    "@angular/forms": "5.2.7",
    "@angular/http": "5.2.7",
    "@angular/material": "^5.2.5",
    "@angular/platform-browser": "5.2.7",
    "@angular/platform-browser-dynamic": "5.2.7",
    "@angular/router": "5.2.7",
    "@types/youtube": "0.0.29",
    "angular-froala-wysiwyg": "^2.7.2-1",
    "angular2-materialize": "^15.1.10",
    "angularfire2": "^4.0.0-rc0",
    "core-js": "^2.4.1",
    "d3": "^4.13.0",
    "firebase": "^3.9.0",
    "hammerjs": "^2.0.8",
    "jquery": "^3.0.0",
    "materialize-css": "^0.100.2",
    "ngx-youtube-player": "0.0.41",
    "rxjs": "^5.5.6",
    "zone.js": "^0.8.4"
  },
  "devDependencies": {
    "@angular/cli": "1.7.2",
    "@angular/compiler-cli": "5.2.7",
    "@types/bootstrap": "^3.3.36",
    "@types/d3": "^4.13.0",
    "@types/jasmine": "2.5.38",
    "@types/node": "~6.0.60",
    "codelyzer": "~2.0.0",
    "jasmine-core": "~2.5.2",
    "jasmine-spec-reporter": "~3.2.0",
    "karma": "~1.4.1",
    "karma-chrome-launcher": "~2.0.0",
    "karma-cli": "~1.0.1",
    "karma-coverage-istanbul-reporter": "^0.2.0",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.1.0",
    "ts-node": "~2.0.0",
    "tslint": "~4.5.0",
    "typescript": "2.6.2"
  }
}

New package.json:

{
  "name": "data-jitsu",
  "version": "0.0.0",
  "license": "MIT",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^6.0.3",
    "@angular/cdk": "^6.3.1",
    "@angular/common": "^6.0.3",
    "@angular/compiler": "^6.0.3",
    "@angular/core": "^6.0.3",
    "@angular/forms": "^6.0.3",
    "@angular/http": "^6.0.3",
    "@angular/material": "^6.2.0",
    "@angular/platform-browser": "^6.0.3",
    "@angular/platform-browser-dynamic": "^6.0.3",
    "@angular/router": "^6.0.3",
    "@types/youtube": "^0.0.29",
    "angular-froala-wysiwyg": "^2.7.2-1",
    "angular2-materialize": "^15.1.10",
    "angularfire2": "^5.0.0-rc.11",
    "core-js": "^2.4.1",
    "d3": "^4.13.0",
    "firebase": "^5.0.3",
    "hammerjs": "^2.0.8",
    "jquery": "^3.0.0",
    "materialize-css": "^0.100.2",
    "ngx-youtube-player": "0.0.41",
    "rxjs": "^6.2.1",
    "zone.js": "^0.8.26"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.6.8",
    "@angular/cli": "~6.0.8",
    "@angular/compiler-cli": "^6.0.3",
    "@angular/language-service": "^6.0.3",
    "@types/bootstrap": "^3.3.36",
    "@types/d3": "^4.13.0",
    "@types/jasmine": "~2.8.6",
    "@types/jasminewd2": "~2.0.3",
    "@types/node": "^10.5.1",
    "codelyzer": "~4.2.1",
    "jasmine-core": "~2.99.1",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~1.7.1",
    "karma-chrome-launcher": "~2.2.0",
    "karma-cli": "~1.0.1",
    "karma-coverage-istanbul-reporter": "~2.0.0",
    "karma-jasmine": "~1.1.1",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.3.0",
    "ts-node": "~5.0.1",
    "tslint": "~5.9.1",
    "typescript": "~2.7.2"
  }
}

When I run npm install using the new package.json updates and then ng serve, I get many compilation errors:

ERROR in src/app/all-matches/all-matches.component.ts(35,39): error TS2339: Property 'takeUntil' does not exist on type 'Observable'. src/app/app.component.ts(28,39): error TS2339: Property 'takeUntil' does not exist on type 'Observable'. src/app/authorization.service.ts(19,41): error TS2339: Property 'of' does not exist on type 'typeof Observable'. src/app/authorization.service.ts(29,37): error TS2339: Property 'of' does not exist on type 'typeof Observable'. src/app/authorization.service.ts(42,39): error TS2339: Property 'of' does not exist on type 'typeof Observable'. src/app/authorization.service.ts(66,39): error TS2339: Property 'of' does not exist on type 'typeof Observable'. src/app/authorization.service.ts(74,37): error TS2339: Property 'of' does not exist on type 'typeof Observable'. src/app/authorization.service.ts(82,39): error TS2339: Property 'of' does not exist on type 'typeof Observable'. src/app/database.service.ts(7,31): error TS2305: Module '"/Users/mf/Desktop/dataJitsu/node_modules/angularfire2/database/index"' has no exported member 'FirebaseListObservable'. src/app/database.service.ts(7,55): error TS2305: Module '"/Users/mf/Desktop/dataJitsu/node_modules/angularfire2/database/index"' has no exported member 'FirebaseObjectObservable'. src/app/match-display/match-display.component.ts(27,49): error TS2339: Property 'takeUntil' does not exist on type 'AngularFireObject<{}>'. src/app/new-match/new-match.component.ts(10,30): error TS2305: Module '"/Users/mf/Desktop/dataJitsu/node_modules/angularfire2/database/index"' has no exported member 'FirebaseListObservable'. src/app/new-match/new-match.component.ts(10,54): error TS2305: Module '"/Users/mf/Desktop/dataJitsu/node_modules/angularfire2/database/index"' has no exported member 'FirebaseObjectObservable'. src/app/new-match/new-match.component.ts(130,37): error TS2339: Property 'switchMap' does not exist on type 'Observable'. src/app/protection.guard.ts(14,34): error TS2339: Property 'map' does not exist on type 'Observable'. src/app/test-db/test-db.component.ts(7,30): error TS2305: Module '"/Users/mf/Desktop/dataJitsu/node_modules/angularfire2/database/index"' has no exported member 'FirebaseListObservable'. src/app/test-db/test-db.component.ts(7,54): error TS2305: Module '"/Users/mf/Desktop/dataJitsu/node_modules/angularfire2/database/index"' has no exported member 'FirebaseObjectObservable'. src/app/user-status-report/user-status-report.component.ts(28,39): error TS2339: Property 'takeUntil' does not exist on type 'Observable'. src/app/user-status-report/user-status-report.component.ts(33,45): error TS2339: Property 'subscribe' does not exist on type 'AngularFireObject<{}>'. src/app/user-status-report/user-status-report.component.ts(35,56): error TS2339: Property 'takeUntil' does not exist on type 'AngularFireObject<{}>'. src/app/user-status-report/user-status-report.component.ts(43,66): error TS2339: Property 'takeUntil' does not exist on type 'AngularFireObject<{}>'.

Most of these errors seemed like they had to do with rxjs, and I think rightly so because I'm using rxjs v.6 in the update, and my understanding is that many things were broken between v.5 and v.6.

I played around with installing rxjs-compat npm install rxjs@6 rxjs-compat@6 --save, and I can confirm that this package, in addition to being a hefty addition, does not resolve any of the errors I'm seeing.

I also automated some of the updating by running ts-lint, per the advice here and here:

npm i -g rxjs-tslint
rxjs-5-to-6-migrate -p [path/to/tsconfig.json]

I get the following message:

No valid rules have been specified for JavaScript files

I'm guessing this means that I didn't use proper ts conventions when using rxjs?

I'm still pretty incompetent when it comes to rxjs, so it's not clear to me exactly what else needs to be refactored.

But I think that my issue actually occurs before the refactoring can of worms:

I took a look at the first error (the

error TS2339: Property 'takeUntil' does not exist on type 'Observable'

one). The error came from a method in my authentication service. In the import statements at the top of this service (and most of the other .ts files, for that matter), my IDE is highlighted a lot of, "cannot find module foo" errors (e.g., "cannot find module, 'rxjs'" for the import statement, import { Observable } from 'rxjs';).

Similar errors in the same file:

import { Injectable, EventEmitter } from '@angular/core'; ("Cannot find module, "@angular/core")

import * as firebase from 'firebase/app'; ("Cannot find module, "firebase/app)

import { Router } from '@angular/router'; ("Cannot find module, "@angular/router")

Here's my app.module.ts file, in case that's useful:

import { MaterializeModule } from 'angular2-materialize'
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { masterFirebaseConfig } from './api-keys';
import { AngularFireModule } from 'angularfire2';
import { AngularFireDatabaseModule } from 'angularfire2/database';
import { AppComponent } from './app.component';
import { YoutubeComponent } from './youtube/youtube.component';
import { routing } from './app.routing';
import { NewMatchComponent } from './new-match/new-match.component';
import { CreateAccountComponent } from './create-account/create-account.component';
import { TestDbComponent } from './test-db/test-db.component';
import { LandingComponent } from './landing/landing.component';
import { MatchDisplayComponent } from './match-display/match-display.component';
import { AuthorizationService } from './authorization.service';
import { AngularFireAuthModule } from 'angularfire2/auth';
import { DatabaseService } from './database.service';
import { TextTransformationService } from './text-transformation.service';
import { ValidationService } from './validation.service';
import { LoginComponent } from './login/login.component';
import { ProtectionGuard } from './protection.guard';
import { AllMatchesComponent } from './all-matches/all-matches.component';
import { AnnotationDisplayComponent } from './annotation-display/annotation-display.component';
import { D3Service } from './d3.service';
import { NotfoundComponent } from './notfound/notfound.component';
import { UserStatusReportComponent } from './user-status-report/user-status-report.component';
import { PaymentOrAnnotationDetailsComponent } from './payment-or-annotation-details/payment-or-annotation-details.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { MatSelectModule } from '@angular/material/select';
import { MatOptionModule } from '@angular/material/core';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material';
import { MatTableModule } from '@angular/material/table';
// import { MatTreeModule } from '@angular/material';
import { MatTreeModule } from '@angular/material/tree';
import { MatSortModule } from '@angular/material';
import { MatDatepickerModule, MatNativeDateModule, MatPaginatorModule } from '@angular/material';
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
import { CdkTreeModule } from '@angular/cdk/tree';


export const firebaseConfig = {
  apiKey: masterFirebaseConfig.apiKey,
  authDomain: masterFirebaseConfig.authDomain,
  databaseURL: masterFirebaseConfig.databaseURL,
  storageBucket: masterFirebaseConfig.storageBucket
};

@NgModule({
  declarations: [
    AppComponent,
    YoutubeComponent,
    NewMatchComponent,
    CreateAccountComponent,
    TestDbComponent,
    LandingComponent,
    MatchDisplayComponent,
    LoginComponent,
    AllMatchesComponent,
    AnnotationDisplayComponent,
    NotfoundComponent,
    UserStatusReportComponent,
    PaymentOrAnnotationDetailsComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    routing,
    MaterializeModule,
    ReactiveFormsModule,
    AngularFireModule.initializeApp(firebaseConfig),
    AngularFireDatabaseModule,
    AngularFireAuthModule,
    BrowserAnimationsModule,
    MatSlideToggleModule,
    CdkTreeModule,
    MatSelectModule,
    MatOptionModule,
    MatInputModule,
    MatNativeDateModule,
    MatDatepickerModule,
    MatTableModule,
    MatSelectModule,
    MatSortModule,
    MatProgressSpinnerModule,
    MatPaginatorModule,
    MatTreeModule
  ],
  providers: [AuthorizationService, DatabaseService, ProtectionGuard, D3Service, ValidationService, TextTransformationService],
  bootstrap: [AppComponent]
})
export class AppModule { }

And here's the branch of the repo containing all of these issues.

git clone https://github.com/Atticus29/dataJitsu.git
cd dataJitsu
git checkout version-hell-SO 
npm install
ng serve

Any troubleshooting hints or outright solutions to the importing issues are welcome and encouraged!

Answer

madjaoue picture madjaoue · Jul 2, 2018

It looks like your operators are still chained in rxjs 5.x fashion.

So to recap what changed in rxjs6 :

  1. Imports are different. Now, you should import Observable, Subject, BehaviorSubject etc. AND methods that were in 'rxjs/add/observable' differently. So all of these must be imported from 'rxjs'. For example :

    import {Observable, Subject, of, from} from 'rxjs';

    Alternatively, all operators like map, concat, do (which now is called tap) etc. are to be imported from rxjs/operators. so something like :

    import { map, tap, takeUntil} from 'rxjs/operators';

    I think your imports are pretty sane.

  2. You must use pipes instead of chaining your operators. For instance, in your all-matches.components.ts, line 33, if you replace : this.authService.getCurrentUser().takeUntil(this.ngUnsubscribe).subscribe(user=>{

    by

    this.authService.getCurrentUser().pipe(takeUntil(this.ngUnsubscribe)).subscribe(user=>{

    your takeUntil error will disappear.

    In the same fashion, instead of Observable.of(true), you should import of operator and use of(true).

    You can try this in your authorization.service.ts file. All the "of errors" will be fixed.

    maybe you should inspect this

  3. Concerning the import errors regarding custom files, please check the files actually exist. For example :

    ERROR in src/app/app.module.ts(6,38): error TS2307: Cannot find module './api-keys'

    related to

    import { masterFirebaseConfig } from './api-keys'

    is normal, since this file './api-keys' doesn't exist. PS: maybe you don't have these errors if keys are not stored in git, if so ignore this.

  4. Finally, about AngularFire5.0, you should use one of the operators :

    Db.list('items').subscribe(console.log)

    becomes (with valueChanges method) :

    Db.list<Item>('items').valueChanges().subscribe(console.log)

    More info : https://github.com/angular/angularfire2/blob/master/docs/version-5-upgrade.md

Good luck!