dman
dman

Reputation: 11064

Array will never be empty but typescript does not know

I am getting this error Expected at least 1 arguments, but got 0 or more from:

    if (initialValues.length > 0) {
      return Object.assign(...initialValues);
    }

I guess it is complaining that initialValues could be empty. However, the if condition guarantees that it won't be empty. What do I do to make typescript realize this?

Upvotes: 2

Views: 370

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074295

Allowing a length check as a type guard was deemed "too complex" to be added to TypeScript (thanks @jcalz for the link!).

You can take a least three approaches:

Destructure and provide the target explicitly

Since it's not getting it from the length check, I'd probably give it the target object explicitly, like this:

const [target, ...sources] = initialValues;
if (target) {
    return Object.assign(target, ...sources);
}

It's happy with that.

Playground link

Define it as a non-empty array

This answer shows how to define a type for a non-empty array:

type NonEmptyArray<T> = [T, ...T[]];

If initialValues is known at compile-time to always have at least one element, define it using that type:

let initialValues: NonEmptyArray<YourObjectType>;

Then you can remove the if, since you know it'll always be true:

return Object.assign(...initialValues);

Use a type guard

But if it could be empty and the runtime check is needed, you can define a type guard function:

function isNotEmpty<T>(arr: T[]): arr is NonEmptyArray<T> {
    return arr.length > 0;
}

Then it's:

if (isNotEmpty(initialValues)) {
    return Object.assign(...initialValues);
}

Huge thanks to @jcalz and @VLAZ for helping with this answer.

Upvotes: 6

Related Questions