Skip to content

(Indirect) inference of array element type in callback function type does not work #40743

Closed
@danielrentz

Description

@danielrentz

TypeScript Version: 4.0.2

Search Terms: array element type inference callback

Code

Found a problem with type inference when tried to implement functions and array methods taking callbacks, where the array element type will be inferred from the actual array type.

What I have:

  • a helper type ElemT that extracts the element type from an array type.
  • a function type FuncT to be used in array iteration functions.
  • a global function taking an array and a callback.
  • a new array class with a method taking a callback.

The callback wants to pass the array with its actual type as parameter. Therefore, FuncT needs the array type as generic parameter, and must infer the element type for its first parameter.

// helper type to infer element type from array type
type ElemT<AT extends any[]> = AT extends (infer T)[] ? T : never;

// callback function taking element type and array type
type FuncT<AT extends any[]> = (v: ElemT<AT>, a: AT) => void;

// global function
function example<AT extends any[]>(arr: AT, cb: FuncT<AT>) {
    cb(arr[0], arr); // <==== works
}

// class method
class MyArr<T> extends Array<T> {
    public example(cb: FuncT<this>) {
        cb(this[0], this); // <==== fails
    }
}

However, I fond a workaround: When I bake the ElemT into the FuncT it works as expected. But that's a little inconvenient because this has to be done for multiple callback types in my real code.

// callback function taking element type and array type
type FuncT<AT extends any[]> = AT extends (infer T)[] ? (v: T, a: AT) => void : never;

// global function
function example<AT extends any[]>(arr: AT, cb: FuncT<AT>) {
    cb(arr[0], arr); // <==== works
}

// class method
class MyArr<T> extends Array<T> {
    public example(cb: FuncT<this>) {
        cb(this[0], this); // <==== works now
    }
}

Expected behavior:
In MyArr#example, ElemType<this> resolves to T.

Actual behavior:
In MyArr#example, this[0] (with type T) cannot be assigned to ElemT<this>.

Playground Link:
https://www.typescriptlang.org/play?#code/PTAEAsFMBsAdIE6gC4E94oPagJYDsAzRUGSAW0j2RXUlAIUzNAEMEEXUb4AoNDAKLRyAFQA8AQREkAHskoATAM6s8qANoBdAHygAvKCmz5eZaAAU+IkhEBKLaAD8oaQC5QeSADdEAbh48IKAAxizQ0ABGLMEA1vQArnjByDiYeCgsMfgA5iTCFFTcdCymrOycRXy0oABiicHiRpByiiolGjr6Fl7uQqKSItoANKzuUrb6ul6YOAr+gWDZ0JhR0AlJKWk8BPWb6c0sZLDCA8atqh3a5mwIYyIjwRHudUmNgxMA3jygPyER1+x1AAGTQjG62XygIJiPSwgwAd0wCBiSh4AF8AkFgtAWEoVBRkOBMAoeNjcSoALKoCTsMSDM6mFQ0jioOm6L6-UCweIRaA4YKyQ7HSDmR7PeriQk4JTaT7fTm-R7mKVKYGglDgaUQqFgGFw+gsHDQVGcjEYoA

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions