I have the following Data model
Daily Data of a person
interface FetchDocument {
Date : number,
Hours : number,
}
A collection of those data
type Data_Array = Set<FetchDocument> | FetchDocument[]
interface GroupDocument {
name : string,
Data : Data_Array,
}
A sample data for test is as follows
let fetchArray : GroupDocument[] = [
{
name : 'John',
Data : [
{
Date : 13,
'Hours' : 14
},
{
Date : 12,
'Hours' : 433
}
]
}
]
When I want to find on that sample using find method
for(let i= 0; i < fetchArray.length ; i ){
let obj = fetchArray[i].Data.find((obj : FetchDocument) => obj.Date === 13 )
}
The compiler is complaining as below because of Set Type on Data_Array.
error TS2339: Property 'find' does not exist on type 'Data_Array'.
Property 'find' does not exist on type 'Set'.
So what I have tried is try to narrow or re-assign to solve in three ways
Narrowing
if(Array.isArray(fetchArray[i].Data)){
let obj = fetchArray[i].Data.find((obj : FetchDocument) => obj.Date === 13 )
}
if(typeof(fetchArray[i].Data.find) === 'function'){
let obj = fetchArray[i].Data.find((obj : FetchDocument) => obj.Date === 13 )
}
if(fetchArray[i].Data instanceof Array){
let obj = fetchArray[i].Data.find((obj : FetchDocument) => obj.Date === 13 )
}
Re-assigning to array
fetchArray[i].Data = [...fetchArray[i].Data]
let obj = fetchArray[i].Data.find((obj : FetchDocument) => obj.Date === 13 )
fetchArray[i].Data = Array.from(fetchArray[i].Data.values())
let obj = fetchArray[i].Data.find((obj : FetchDocument) => obj.Date === 13 )
But the error can't be solved so what can I do to resolve it.
Playground link : Link
Set is used when fetching data to detect duplicate data so changing it will cause for changing code on other part of codebase
CodePudding user response:
This is due what we call Temporal Uncertainty
. Typescript doesn't know if there's any other codes changing the content of fetchArray
that could lead to a different value while executing the code.
There is no need to explicit type assertion whatsoever, just save the value you wanna check in another variable as soon as you validate it
for (let i = 0; i < fetchArray.length; i ){
let arr = fetchArray[i].Data;
if (arr instanceof Array) {
let obj = arr.find((obj : FetchDocument) => obj.Date === 13)
}
}
CodePudding user response:
You probably need to use Type Assertions
in this case, but if the data is not an array, it will cause errors during runtime
that's why you should also be careful about runtime errors
.
Here is how you can do this,
for(let i= 0; i < fetchArray.length ; i ){
// treat data as a FetchDocument[] type note! it can be another type on run time
const data = fetchArray[i].Data as FetchDocument[]
// consider use error handling here
let obj = data.find((obj : FetchDocument) => obj.Date === 13 )
}
Updated
You can also use Array.from
method without adding any extra if
for(let i= 0; i < fetchArray.length ; i ){
let obj = Array.from (fetchArray[i].Data)
.find((obj : FetchDocument) => obj.Date === 13 )
}