Reputation: 4561
I have a code working with the any
type, check the comment //HERE TYPE ANY
:
I need that to be able to push data into that array, as you will be able to se below in the code in the //NEED ANY TYPE TO PUSH INTO THE ARRAY
line.
const ProjectList = () => {
const [projects, setProjects] = useState<IFirebaseProject[]>();
useEffect(() => {
let data:any[] = []; //HERE TYPE ANY
firebase
.firestore()
.collection("projects")
.onSnapshot((snapshot) => {
let changes = snapshot.docChanges();
changes.forEach(change => {console.log(change.doc.data())})
const fbProjects = changes.map( (change) => ({
id: change.doc.id,
...change.doc.data()
}));
fbProjects.forEach(fbProject => data.push(fbProject)) //NEED ANY TYPE TO PUSH INTO THE ARRAY
setProjects([...data]);
});
}, []);
My problem is that I cannot enforce the type (although I know it) for the specific part of the code:
const fbProjects = changes.map( (change) => ({
id: change.doc.id,
...change.doc.data()
}));
I know the type obtained by ...change.doc.data()
, but how can I enforce my type, so that fbProjects
meets a determined type which I define?
This is the type of fbProjects
:
interface IFirebaseProject {
id: string,
authorFirstName: string,
authorId: string,
authorLastName: string
content: string
createdAt: Date
title: string
}
So it has the id property, and I know that ...change.doc.data()
has the rest of the properties.
If I use my IFirebaseProject
instead of any
I obtain an error when I push the project in the array (fbProjects.forEach( fbProject => data.push(fbProject))
) because obviously does not meet the type.
The error I obtain is:
Argument of type '{ id: string; }' is not assignable to parameter of type 'IFirebaseProject'. Type '{ id: string; }' is missing the following properties from type 'IFirebaseProject': authorFirstName, authorId, authorLastName, content, and 2 more.ts(2345)
Edit: Console output:
(One of this objects for each of the registers in the database logged with the .forEach
)
Upvotes: 0
Views: 549
Reputation: 12071
You could tell TypeScript to treat the object returned from map
as IFirebaseProject
:
const fbProjects = changes.map((change) => ({
id: change.doc.id,
...change.doc.data()
}) as IFirebaseProject);
Upvotes: 1
Reputation: 4561
I split my types like this:
interface IFirebaseProject extends Destructured {
id: string,
}
interface Destructured {
authorFirstName: string,
authorId: string,
authorLastName: string
content: string
createdAt: Date
title: string
}
Then I could set the type of the destructured part like this.
const fbProjects = changes.map( (change) => ({
id: change.doc.id,
...change.doc.data() as Destructured
}));
That did the work. In case there is a more proficient way to solve this, I'll be glad to know.
Upvotes: 1