Skip to content

Narrowing of indexed access type only allows apparent type access; don't allow assignability #32502

Closed
@charles-toller

Description

@charles-toller

TypeScript Version: 3.6.0-dev.20190720

Search Terms: type narrowing undefined generics early return

Code

type BaseEvents = {[event: string]: Array<any>};
type Cbs<A extends BaseEvents> = {
    [P in keyof A]: Array<(...args: A[P]) => boolean | Promise<boolean>> | undefined;
}
export class Events<T extends BaseEvents> {
    private cbs: Cbs<T> = {} as any;
    async emit<P extends keyof T>(event: P, ...args: T[P]) {
        const arr = this.cbs[event]; // typeof arr = ((...args: T[P]) => boolean | Promise<boolean>)[] | undefined
        type NonNullArr = NonNullable<typeof arr>; // ((...args: T[P]) => boolean | Promise<boolean>)[]
        if (typeof arr === 'undefined') {
            return;
        }
        // typeof arr should now be ((...args: T[P]) => boolean | Promise<boolean>)[]
        const nonNullArr: NonNullArr = arr; // TS2322: Type '((...args: T[P]) => boolean | Promise<boolean>)[] | undefined' is not assignable to type 'NonNullable<Cbs<T>[P]>'.
                                            // Type 'undefined' is not assignable to type 'NonNullable<Cbs<T>[P]>'.
        for (const cb of arr) { // TS2488: Type 'Cbs<T>[P]' must have a '[Symbol.iterator]()' method that returns an iterator.

        }
        for (const cb2 of nonNullArr) { // No error

        }
    }
}

Expected behavior: Compiles without errors.

Actual behavior: Several errors relating to arr not narrowing out the undefined portion of the argument:

Error:(14, 15) TS2322: Type '((...args: T[P]) => boolean | Promise<boolean>)[] | undefined' is not assignable to type 'NonNullable<Cbs<T>[P]>'.
  Type 'undefined' is not assignable to type 'NonNullable<Cbs<T>[P]>'.
Error:(16, 26) TS2488: Type 'Cbs<T>[P]' must have a '[Symbol.iterator]()' method that returns an iterator.

Playground Link

Related Issues:

#1726 (closed by design, this is different because we can assume any array is not undefined)

#31456 (this example has a constraint)

Metadata

Metadata

Assignees

Labels

Design LimitationConstraints of the existing architecture prevent this from being fixedDomain: Indexed Access TypesThe issue relates to accessing subtypes via index accessDuplicateAn existing issue was already created

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions