typescript - Ako môžem spraviť generický typ voliteľným?
Mám nasledujúcu metódu zaznamenávania:
private logData<T, S>(operation: string, responseData: T, requestData?: S) {
this.logger.log(operation + ' ' + this.url);
if (requestData) {
this.logger.log('SENT');
this.logger.log(requestData);
}
this.logger.log('RECEIVED');
this.logger.log(responseData);
return responseData;
}
requestData je voliteľné. Chcem byť schopný volať logData bez toho, aby som musel špecifikovať typ S, keď neposielam requestData do metódy: namiesto this.logData<T, any>('GET', data) chcem volať this.logData<T>('GET', data).
Existuje spôsob, ako to dosiahnuť?
Odpoveď č. 1
Od verzie TypeScript 2.3 môžete používať predvolené hodnoty generických parametrov.
private logData<T, S = {}>(operation: string, responseData: T, requestData?: S) {
// your implementation here
}
Odpoveď č. 2
TS Update 2020: Zadaním
voidsa generický typ stane voliteľným.
type SomeType<T = void> = OtherType<T>;
Odpoveď vyššie, kde je ako objekt uvedená predvolená hodnota, ju robí voliteľnou, ale stále jej dáva hodnotu.
Príklad s predvolenou hodnotou typu je
{}:
type BaseFunctionType<T1, T2> = (a:T1, b:T2) => void;
type FunctionType<T = {}> = BaseFunctionType<{name: string}, T>
const someFunction:FunctionType = (a) => {
}
someFunction({ name: "Siraj" });
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Expected 2 arguments, but got 1.(2554)
Odkaz na ihrisko
Príklad s predvolenou hodnotou generického typu je
void
type BaseFunctionType<T1, T2> = (a:T1, b:T2) => void;
type FunctionType<T = void> = BaseFunctionType<{name: string}, T>
const someFunction:FunctionType = (a) => {
}
someFunction({ name: "Siraj" })
Toto je dobré čítanie o tom, ako spraviť generiká voliteľnými.
Voliteľný generický typ v Typescripte
Odkaz na ihrisko
Odpoveď č. 3
Podľa TypeScript 2.2 (môžete to vyskúšať v TS Playground) sa volanie this.logData("GET", data) (s data typu T) úspešne odvodí ako this.logData<T, {}>("GET", data).
Preťaženie navrhnuté Davidom Bohunekom sa môže použiť, ak odvodzovanie zlyhá s verziou TS, ktorú používate. Každopádne, uistite sa, že druhý podpis je najprv deklarovaný a potom definovaný, inak by sa nezapojil do dostupných preťažení.
// Declarations
private logData<T>(operation: string, responseData: T);
private logData<T, S>(operation: string, responseData: T, requestData?: S);
// Definition
private logData<T, S>(operation: string, responseData: T, requestData?: S) {
// Body
}
Odpoveď č. 4
Ak hľadáte voliteľný generický typ v deklarácii typu/rozhrania, toto vám môže pomôcť.
(prišiel som hľadať toto, našiel som iba odpovede týkajúce sa všeobecných deklarácií funkcií. Sirajova odpoveď ma nasmerovala správnym smerom.)
type ResponseWithMessage = {
message: string;
};
interface ResponseWithData<T> extends ResponseWithMessage {
data: T;
}
export type ResponseObject<T = void> = T extends void
? ResponseWithMessage
: ResponseWithData<T>;
