'How can I create a generic function that listens for firestore updates?

In my data model class I have two arrays that I initialise as empty arrays. Within the class initialiser I add a snapshot listener that listens to the arrays relevant collection. Both models conform to the Codable protocol so that I can map the fetched firestore data. The ModelData class is going to contain more arrays so to have these snapshot listener blocks of code in the initialiser feels like I am violating the DRY principle.

final class ModelData: ObservableObject {
    @Published var tasks: [Task] = []
    @Published var projects: [Project] = []
    
    let db = Firestore.firestore()
    
    init() {
        db
            .collection("tasks")
            .addSnapshotListener { querySnapshot, error in
                if let documents = querySnapshot?.documents {
                    self.tasks = documents.compactMap { queryDocumentSnapshot in
                        try? queryDocumentSnapshot.data(as: Task.self)
                    }
                }
            }
        
        db
            .collection("projects")
            .addSnapshotListener { querySnapshot, error in
                if let documents = querySnapshot?.documents {
                    self.projects = documents.compactMap { queryDocumentSnapshot in
                        try? queryDocumentSnapshot.data(as: Project.self)
                    }
                }
            }
    }
}

I would like to know if it is possible to remove the code from the initialiser and make it into a generic function? Is the following function signature below a step in the right direction?

func listen<T: Codable>(_ array: [T]) {
    ...
}

Update #1

I have the generic listen function working by passing in the type and then on the specific sections where I map data or list a collection I have a condition statement that checks the type. I still feel as though I am repeating myself when mapping the data. Could the complexity of this function be minimised in anyway?
final class ModelData: ObservableObject {
    @Published var tasks: [Task] = []
    @Published var projects: [Project] = []
    
    let db = Firestore.firestore()
    
    init() {
        listen(type: Task.self)
        listen(type: Project.self)
    }
    
    func listen<T: Codable>(type: T.Type) {
        db
            .collection(type == Task.self ? "tasks" : "projects")
            .whereField("userID", isEqualTo: "tXHIUJ6YUCORv6BWGZaxsYzvQBY2")
            .addSnapshotListener { querySnapshot, error in
                if let documents = querySnapshot?.documents {
                    if type == Task.self {
                        self.tasks = documents.compactMap { queryDocumentSnapshot in
                            try? queryDocumentSnapshot.data(as: T.self) as? Task
                        }
                    } else {
                        self.projects = documents.compactMap { queryDocumentSnapshot in
                            try? queryDocumentSnapshot.data(as: T.self) as? Project
                        }
                    }
                }
            }
    }
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source