Skip to content

Type parameter on ts.some/ts.find is too narrow when called on union of arrays, works with explicit instantiation #52179

@jakebailey

Description

@jakebailey

This is a follow-up to #52111 and #52123.

In the below code, every works as expected, which is new as of #52123. However, the some function can't be called on the array type at all, even though reasonably there's a top type which works (A), just like it works for every.

interface A           { a: string; }
interface B extends A { b: string; }
interface C extends A { c: string; }

declare function isC(x: A): x is C;

declare function every<T, U extends T>(array: readonly T[], callback: (element: T, index: number) => element is U): array is readonly U[];
declare function every<T, U extends T>(array: readonly T[] | undefined, callback: (element: T, index: number) => element is U): array is readonly U[] | undefined;
declare function every<T>(array: readonly T[] | undefined, callback: (element: T, index: number) => boolean): boolean;

declare function some<T>(array: readonly T[] | undefined): array is readonly T[];
declare function some<T>(array: readonly T[] | undefined, predicate: (value: T) => boolean): boolean;

function foo(array: readonly B[] | readonly C[] | undefined) {
    if (every(array, isC)) {
        array;
        // ^?
    }

    if (some(array)) {
        array;
        // ^?
    }

    if (some(array, isC)) {
        array;
        // ^?
    }
    
    if (some<A>(array)) {
        array;
        // ^?
    }

    if (some<A>(array, isC)) {
        array;
        // ^?
    }
}
Output
"use strict";
function foo(array) {
    if (every(array, isC)) {
        array;
        // ^?
    }
    if (some(array)) {
        array;
        // ^?
    }
    if (some(array, isC)) {
        array;
        // ^?
    }
    if (some(array)) {
        array;
        // ^?
    }
    if (some(array, isC)) {
        array;
        // ^?
    }
}
Compiler Options
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true,
    "strictBindCallApply": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "alwaysStrict": true,
    "esModuleInterop": true,
    "declaration": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "target": "ES2017",
    "jsx": "react",
    "module": "ESNext",
    "moduleResolution": "node"
  }
}

Playground Link: Provided

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions