typescript - Generiske typer for tupler


Er det mulig å definere en generell variabel som en Tupl?

Eksempelet: la oss bruke timer-API og setTimeout

den første overbelastningen ser slik ut:

var timeoutID = scope.setTimeout(function[, delay, param1, param2, ...]);

funksjonen kalles med param1, param2,... etter en viss periode.

Hvordan kan det uttrykkes at funksjonen aksepterer argumenter av samme type som param1, param2, ...?

Jeg prøvde:

public setTimeout<T>( 
callback:(...args: T) => void) | string, 
delay, ...args: T) {}

Men det fungerer ikke siden T ikke kan holde tuples som [string, int].

Er det en måte å uttrykke dette på i TypeScript?

Svar #1

Dessverre ser jeg at den eneste måten å gjøre dette på er å erklære flere overbelastninger av funksjonen med økende antall parametere, med en tilbakefall til any[] hvis antall parametere er større enn et definert maksimum. For de fleste praktiske situasjoner bør dette gi den som kaller funksjonen en god typet opplevelse (siden parametrene til callbacken vil få sine parametertyper utledet), selv om definisjonen vil være mye mer arbeid å skrive. For setTimeout bør 3 være et tilstrekkelig antall parametere, men du kan legge til flere om nødvendig:

export declare function setTimeout<T1>( callback:(args1: T1) => void | string, args: T1);
export declare function setTimeout<T1, T2>( callback:(arg1: T1, arg2: T2) => void | string, arg1: T1, arg2: T2);
export declare function setTimeout<T1, T2, T3>( callback:(arg1: T1, arg2: T2, arg3: T3) => void | string, arg1: T1, arg2: T2, arg3: T3);
export declare function setTimeout(callback:(...args: any[]) => void | string, ...args: any[]);


setTimeout((s,d)=> { 
    console.log(s);  // s is string
    d= d+1; // d is a number
}, "", 3);

Overbelastningen med any[] bør være den siste i listen.

Merk: Hvis det er en mismatch mellom callback-argumenter og funksjonsargumenter, vil koden fortsatt kompilere siden den faller tilbake til any[]-versjonen:

// Still compiles
setTimeout((s : string, d: string)=> { 
    // Code
}, "", 3);