TypeScript: Spreads instantiated with array subtypes types exhibit bad behavior

Found by playing around with @mattmccutchen’s example at https://github.com/Microsoft/TypeScript/issues/26013#issuecomment-409330936:

interface CoolArray<E> extends Array<E> { 
    hello: number;
}

declare function foo<T extends any[]>(cb: (...args: T) => void): void;

foo<CoolArray<any>>();    // error
foo<CoolArray<any>>(100); // error
foo<CoolArray<any>>(foo); // no error!!

Expected: All of these calls produce an error and have a good error message. Actual: The first two have bad errors, the last one is considered okay.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 16 (16 by maintainers)

Most upvoted comments

@mattmccutchen Unless we introduce a whole new kind of constraint I’m not sure we can do any better than #26676, and even then it would be a breaking change since it would be stricter than the assignable to any[] requirement we have now. I think scenarios such as the following need to work:

function call<T extends unknown[], U>(f: (...args: T) => U, ...args: T) {
    return f(...args);
}

which means spreading a T needs to be of type T. As I see it, the only way to tighten it all down is to catch it early by having a constraint that only permits Array<T> or tuples. But given how close we are with the current solution and how hard you have to work to expose the unsoundness, I think we’re fine.