Home > Enterprise >  Type 'string | undefined' is not > assignable to type 'string'
Type 'string | undefined' is not > assignable to type 'string'

Time:10-18

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

}

Playground Link

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.

  • Related