Reputation: 588
Shortly said, I know I can do this:
function my_function() : Error {
return some_generic_function<ReturnType<typeof my_function>>();
}
But is there a way to use something like the this
keyword to refer to the function that contains the call, but without using it's name? Like:
function my_function() : Error {
//This does not work, ofc
return some_generic_function<ReturnType<typeof this>>();
}
More context:
I have multiple service-like functions that all return a Promise with the same pattern of resolve
/reject
. Thus, I made a generic function and want to be able to use it in each of my service-like function.
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>>()
}
One way I would like to modify that return is to have something generic instead of the name of the function inside ReturnType<typeof function_name>
Solution:
@captain-yossarian's answer is great. I let TypeScript infer my types. Here's my code:
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
}
);
Upvotes: 2
Views: 53
Reputation: 33091
Technically it is possible. some_generic_function
should expect generic parameter.
const foo = <T,>() => null as any
function my_function(): Error {
return foo<ReturnType<typeof my_function>>();
}
But I'm not sure if it is a good way to go.
You are passing explicit generic parameter to foo
inside my_function
but you don't use it at all.
It will be better if you share a bit more context.
UPDATE
Rule of thumb: in 80% you should not use explicit generics when you calling a function. TS should be able to infer it.
Consider next example:
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)
}
Upvotes: 1