javascript - Finns det ett sätt att använda ReturnType inuti en funktion och referera till funktionen utan att använda dess namn?
Kort sagt, jag vet att jag kan göra detta:
function my_function() : Error {
return some_generic_function<ReturnType<typeof my_function>>();
}
Men finns det ett sätt att använda något som this-nyckelordet för att referera till funktionen som innehåller anropet, men utan att använda dess namn? Som:
function my_function() : Error {
//This does not work, ofc
return some_generic_function<ReturnType<typeof this>>();
}
Mer kontext:
Jag har flera service-liknande funktioner som alla returnerar ett Promise med samma mönster av resolve/reject. Därför har jag gjort en generell funktion och vill kunna använda den i varje av mina service-liknande funktioner.
function my_generic_return<T> (data?:T, error?: Error): Promise<T> {
return new Promise((resolve, reject) => {
if (typeof data !== 'undefined') {
return resolve(data);
}
return reject();
});
}
function service1() : Promise<type1> {
const data : type1 | undefined ...
// ...
// But this line is kinda ugly
return my_generic_return<ReturnType<typeof service1>>()
}
function service2() : Promise<type2> {
const data : type2 | undefined ...
// ...
// But this line is kinda ugly
return my_generic_return<ReturnType<typeof service2>>()
}
Ett sätt jag skulle vilja ändra den returvärdet är att ha något generiskt istället för namnet på funktionen inuti ReturnType<typeof function_name>
Lösning:
@captain-yossarians svar är utmärkt. Jag låter TypeScript härleda mina typer. Här är min kod:
function my_generic_return<T>(data?: NonNullable<T>, error?: Error)
: Promise<NonNullable<T>> {
// I use NonNullable since I never return a Promise with an undefined object.
return new Promise((resolve, reject) => {
if (typeof data !== 'undefined') {
return resolve(data);
}
if (error instanceof Error) {
return reject(error)
}
return reject(new Error("Unknown error");
});
}
function service1() {
const data : type1 | undefined = undefined
// We may set data here...
return my_generic_return(data)
}
function service2() {
const data : type2 | undefined = undefined
// We may set data here...
return my_generic_return(data)
}
const global_data: type2 = new type2();
service2.then(
// Param correctly seen as 'type2'
// This is why I used NonNullable in the generic
// Otherwise it would be seens as 'type2 | undefined'
// because that's the type of data inside service2
(data) => {
global_data = data
}
);
Svar #1
Tekniskt sett är det möjligt. some_generic_function bör förvänta sig en generisk parameter.
const foo = <T,>() => null as any
function my_function(): Error {
return foo<ReturnType<typeof my_function>>();
}
Men jag är inte säker på om det är ett bra sätt att gå.
Du skickar en explicit generisk parameter till foo inuti my_function men du använder den inte alls. Det skulle vara bättre om du delade lite mer kontext.
UPPDATERING
Tumregel: i 80% av fallen bör du inte använda explicita generics när du anropar en funktion. TS bör kunna härleda det.
Tänk på nästa exempel:
function my_generic_return<T>(data?: T, error?: Error): Promise<T> {
return new Promise((resolve, reject) => {
if (typeof data !== 'undefined') {
return resolve(data);
}
return reject();
});
}
type Foo = {
tag: 'foo'
}
function service1<T>(data: T) {
return my_generic_return(data)
}
// return type is Promise<Foo>
function service2() {
const data: Foo = null as any
return my_generic_return(data)
}
