Using AngularFire2 in a secure and reliable manner

Within my schema

import { DocumentReference } from 'angularfire2/firestore';

type DogType = 'good' | 'bad';

interface Dog {
  ref: DocumentReference;
}
interface GoodDog extends Dog {
  props: GoodDogProps;
}
interface GoodDogProps {
  // Props
}
interface BadDog extends Dog {
  props: BadDogProps;
}
interface BadDogProps {
  // Props
}

I also have an ApiService

@Injectable({
  providedIn: 'root'
})
export class DogApiService {
  private dogs: {
    good: AngularFirestoreCollection<GoodDogProps>;
    bad: AngularFirestoreCollection<GoodDogProps>;
  };
  constructor(private db: AngularFirestore) {
    this.dogs = {
      good: this.db.collection('goodDogs'),
      bad: this.db.collection('badDogs')
    };
  }

  public listDogs(type: DogType) {
    return this.dogs[type].ref.get().then(collection =>
      collection.docs.map(doc => {
        return {
          ref: doc.ref,
          props: doc.data()
        };
      })
    );
  }
}

But I am facing an issue with TypeScript:

When I call listDogs('good'), I want TypeScript to indicate that this function will return a Promise<GoodDogs[]>. I attempted using generics but couldn't resolve the TS errors.

A bit of context:

  • I cannot utilize AngularFirestore.valueChanges() as it doesn't provide DocumentReference
  • I prefer not to use the alternative AngularFirestore.snapshotChanges method, as I solely require a simple Promise
  • GoodDog and BadDog are the types I need for my App
  • GoodDogProps and BadDogProps define the Firebase schema

Answer №1

If you want to ensure that the signature for listDogs is correct, consider using lookup types. You might have to include some type casts in the code:

type DogType = 'good' | 'bad';

interface Dog<P> { 
  ref: DocumentReference;
  props: P;
}
interface GoodDogProps {
  // Props
}
interface BadDogProps {
  // Props
}
interface DogTypePropsMapping { 
  good: GoodDogProps;
  bad: BadDogProps;
}

export class DogApiService {
  private dogs: { [T in DogType]: AngularFirestoreCollection<DogTypePropsMapping[T]>};
  constructor(private db: AngularFirestore) {
    this.dogs = {
      good: this.db.collection('goodDogs'),
      bad: this.db.collection('badDogs')
    };
  }

  public listDogs<T extends DogType>(type: T): Dog<DogTypePropsMapping[T]>[] {
    return this.dogs[type].ref.get().then(collection =>
      collection.docs.map(doc => {
        return {
          ref: doc.ref,
          props: doc.data()
        };
      })
    );
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

show the stored value inside the useRef variable

One of my challenges involves a variable const prediction = useRef<any>(null); A button triggers a function that updates the variable's value: function showResult() { classifier.current.classify(capture, (result) => { ...

Error message from @types/eslint: The members ChainExpression and ImportExpression from ESTree are not being exported

Encountered some issues while running my Angular application using npm start. Errors are caused by missing exports for 'ChainExpression' and 'ImportExpression' in the ESTree interface... Refer to the image below for more details: http ...

Issue with Undefined Array in Angular 2 App

I've encountered an issue while attempting to save JSON data from my API into an array of Model objects. Despite trying different approaches, the console always logs "undefined" when I try to print the array. This even happens with a simple array that ...

Is there a way to execute the run function of a different Component in Angular 7 without causing the current

Is there a way to execute the ngOnInit() function from one component inside another component without needing to refresh the existing page? ...

Type-safe Immutable.js Records with TypeScript

I'm struggling to find a suitable solution for my query. I am aiming to define data types using an interface in TypeScript, but my data consists of Immutable.js records making it more complex. Please refer to the example provided below. interface tre ...

The useForm function from react-hook-form is triggered each time a page is routed in Nextjs

Hey there, I'm just starting out with Next.js (v14) and I'm trying to create a multi-page form using react-hook-form. But I'm encountering an issue where the useForm function is being executed every time, and the defaultValues are being set ...

The method beforeEach in angular2/testing seems to be failing as it is not

Currently, I am utilizing Gulp, Gulp-Jasmine, and SystemJS to conduct tests on an Angular2 demo application. The setup is fairly straightforward. I have successfully implemented a System.config block and loaded the spec file. However, I encounter an error ...

Monitoring real-time updates in Angular components using Firebase

I am looking to access data across multiple components and have implemented a service to retrieve the necessary data. However, I am encountering an issue when attempting to observe this data. Here is my current code: @Injectable() export class Notification ...

Typescript raises an issue regarding a React component's optional prop potentially being undefined

I have a basic React component that looks like this: interface ComponentProperties { onClick?: () => void; } const CustomComponent = (properties: ComponentProperties) => { if (!properties.onClick) { return <></>; } ...

Filtering multiple disordered words using Angular

Currently, I am facing an issue with filtering elements from a list in my code. My goal is to filter elements when entering multiple words at once, regardless of their order. At the moment, I can only filter elements if I input the words in the correct seq ...

Tips for synchronizing the display of a table with the server response in an Angular application

* Project I am currently working on a project that involves retrieving player data from a json server and displaying it in a standard table format with a paginator. * Issue The challenge I'm facing is ensuring that the table data is loaded before th ...

Is there a way to apply a filter to an object without using an additional map function?

When an error occurs, my pipe returns of{}. I need to filter it to redirect to other code flows. Currently, I am using the following scenario. Is there a way to remove the map and filter it within the existing filter? readonly k$ = combineLatest( [t ...

Is it possible to design a Typescript type that only contains one property from a defined set and is indexable by that set as well?

I have the different types listed below: type OrBranch = { or: Branch[] } type AndBranch = { and: Branch[] } I need a type called Branch that can either be an OrBranch or an AndBranch. I initially attempted this: type Branch = AndBrand | OrBranch ...

Adjusting the array when items in the multi-select dropdown are changed (selected or unselected)

I am looking to create a multi-select dropdown in Angular where the selected values are displayed as chip tags. Users should be able to unselect a value by clicking on the 'X' sign next to the chip tag, removing it from the selection. <searcha ...

Storing information from a form into a database with the help of TypeORM on Angular 6

Utilizing TypeORM alongside Angular to store form data in the database has been successful. The connection configuration is correct, allowing for data storage from the backend. { "type": "mssql", "host": "***", ...

Executing MongoDB collection operations with array filtering

I am looking to count records based on tags and filter them before including in specific groups // data in database {tags: ['video', 'Alex'], ... }, {tags: ['video', 'John'], ... }, {tags: ['video', 'J ...

Using lodash to combine the values of identical objects

As a newcomer to development, I am looking to group similar objects within an array of JSON objects. Here is an example of my JSON array: var data = [ { zone: "Bottom", group: "Bottom girders", original: 7, ...

Methods for populating an object with Interface type and returning it

This is my function that populates an object based on interface type: public _fillAddModel<T>(lessonId: number, studyPeriodId: number, confirmed: boolean = false): T { let data: T; data = { lesson: this.substitution.lessonNumber, ...

Ensure that AngularJs Views are consistently typed in MVC

One of the reasons I find MVC so appealing is the strong typing of both the Views and the Controllers. This allows me to access a variable directly from the Model in the View using Razor syntax: <p> @Model.MyProperty // strongly typed </p> ...

Guide to loading a minified file in Angular 2 with Gulp Uglify for TypeScript Bundled File minimization

In my Angular 2 application, I have set the TypeScript compiler options to generate a single outFile named Scripts1.js along with Scripts1.js.map. Within my index.html file: <script src="Scripts/Script1.js"></script> <script> ...