funktion - Videregivelse af klassemetode som parameter i Typescript


Jeg søger efter en mulighed for at videregive en klassemetode til en funktion, som derefter kan udføre den funktion på en instans af den klasse. Noget i stil med denne pseudokode: (bemærk, at dette er et abstrakt eksempel)

class Foo {
    public somefunc() {
        // do some
    }
    public anyfunc() {
        // do any
    }
}

function bar(obj: Foo ,func: "Foo.method") {  // "that's what im looking for"
    obj.func();
}

bar(new Foo(), Foo.somefunc);  // do some
bar(new Foo(), Foo.anyfunc);  // do any

Er der en mulighed for at gøre dette?

Jeg ved, jeg kunne lave noget lignende:

class Foo {
    static somefunc(fooObj: Foo) {
        // do some
    }
    static anyfunc(fooObj: Foo) {
        // do any
    }
}

interface func {
    (fooObj: Foo);
}

function bar(obj: Foo, fn: func) {
    fn(obj);
}

bar(new Foo(), Foo.somefunc);  // do some
bar(new Foo(), Foo.anyfunc);  // do any

men det involverer statiske funktioner, hvilket jeg ikke ønsker.

Svar #1

Dette kontrollerer ikke ved kompileringstidspunktet, at funktionen kom fra en Foo, men gør resten:

class Foo {
    public somefunc() {
        // do some
    }
    public anyfunc() {
        // do any
    }
}

function bar(obj: Foo ,func: () => void) {
    func.call(obj);
}

bar(new Foo(), Foo.prototype.somefunc);  // do some
bar(new Foo(), Foo.prototype.anyfunc);  // do any

Svar #2

Typescript 2+ løsning

TL;DR: TypeScript Playground, Repo med en demo

Fordele:

  1. Kontrol under kompilering.
  2. Vil ikke lade dig miste denne kontekst, når du videregiver en instansmetode.
  3. Tab ikke ydeevne: du behøver ikke at erklære klassens metoder som instansmetoder (f.eks. public somefunc =() => { return this.prop; }) - Læs mere.
  4. Rør ikke ved en klasses prototype.
  5. Konsistent signaturmønster: at videregive en callback som det første argument og thisArg som det andet (f.eks. Array.prototype.map()).

Overvej følgende kode:

class Foo {
    private result: number = 42;

    public func(this: Foo): number {
        return this.result;
    }
}

function action(): void {
    console.log("Hello world!");
}

function bar(callbackFn: (this: void) => any, thisArg?: undefined): any;
function bar<T>(callbackFn: (this: T) => any, thisArg: T): any;
function bar<T, TResult>(callbackFn: (this: T) => TResult, thisArg: T): TResult {
    return callbackFn.call(thisArg);
}

const foo = new Foo();

bar(action); // success
bar(foo.func); // ERROR: forgot to pass `thisArg`
bar(foo.func, foo); // success

Ret din opmærksomhed mod signaturen af Foo#func:

public func(this: Foo): number

Det angiver, at denne funktion skal kaldes i en kontekst af klassens instans. Dette er den første del af løsningen, som ikke vil lade dig miste this-konteksten.

Den anden del er bar-funktionsoverbelastninger:

function bar(callbackFn: (this: void) => any, thisArg?: undefined): any;
function bar<T>(callbackFn: (this: T) => any, thisArg: T): any;
function bar<T, TResult>(callbackFn: (this: T) => TResult, thisArg: T): TResult

Dette ville lade dig videregive generiske funktioner såvel som instansmetoder.

Du kan lære mere om disse emner i TypeScript-håndbogen:

  1. this parametre i callbacks
  2. Funktionsoverbelastninger
  3. Generika

Relaterede artikler