I just want to compare two arrays together but one of the array comes from a 3rd party AWS, which I cannot make sure that it exists.
Somehow I am not able to bypass my error. I am protecting the call of the function by returning and I still get this error:
Argument of type '(string | undefined)[]' is not assignable to parameter of type 'string[]'. Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'.ts(2345)
I'm also getting a warning trying to check the both arrays match.
const fileNames = files?.Contents?.filter((content) => content.Key?.endsWith('.docx')).map((content) =>
content.Key?.replace(FOLDER_PATH, '')
);
if (!fileNames || !fileNames.length || fileNames === undefined) {
return;
}
compareFileNames(fileNames, configFiles) // compilation error above
// ...
const compareFileNames = (a: string[], b: string[]) => {
if (a.length !== b.length) return false;
return a.sort().toString() === b.sort().toString(); // Warning Move this array "sort" operation to a separate statement
}
What are the problems here?
CodePudding user response:
In your example you write:
if(!data || typeof data === 'undefined' || typeof data[0] === 'undefined') {
return;
}
which can be shortened to:
if(data.some(item => item === undefined)) {
return;
}
Next, you're passing data
to a method that only accepts string[]
but data
still has the type Array<string | undefined>
because typescript cannot infer that there are no undefined
elements inside of the array based on the if condition.
You can either cast the array to a string[]
manually, or use a typeguard:
Cast:
const main = () => {
const data: Array<string | undefined> = [undefined];
if(data.some(item => item === undefined)) {
return;
}
foo(data as Array<string>);
}
Typeguard:
const main = () => {
const data: Array<string | undefined> = [undefined];
if(!isNotUndefinedArray(data)) {
return;
}
foo(data);
}
function isNotUndefinedArray<T>(a_arr: Array<T | undefined>): a_arr is Array<T> {
return !a_arr.some(a_item => a_item === undefined);
}
CodePudding user response:
The expression
.map((content) => content.Key?.replace(FOLDER_PATH, ''))
returns either a string or undefined. Therefor the inferred type of fileNames
is (string | undefined)[]
.
You can change your statement to this
const fileNames: string[] = files?.Contents?
.filter((content) => content.Key?.endsWith('.docx'))
.map((content) =>
content.Key?.replace(FOLDER_PATH, '')
)
.filter( s => s);
The last filter
removes all undefined entries.