Reputation: 7462
Given this definition:
declare function foo<T>(): { bar: T }
// <T>() => { bar: T }
type Foo = typeof foo;
How can one provide specialization to the generic function by its type?
What I want to achieve is to be able to do something like this:
// { bar: number }
type FooResult = ReturnType<Foo<number>>;
But TypeScript complaints that Foo
itself is not generic - the function it types is.
Upvotes: 2
Views: 697
Reputation: 327624
TypeScript doesn't really support the kind of higher-order typing you'd need to get this from ReturnType
... it's a known design limitation. So all you have available is a variety of workarounds. Here are the ones I can think of off the top of my head:
Do it manually. This is essentially a non-answer, but could be the best way forward since it doesn't rely on any weird type system tricks:
type FooResult<T> = { bar: T };
type FooResultNumber = FooResult<number>; // {bar: number}
Pretend to actually call foo()
and get its result. TypeScript doesn't support arbitrary type queries, so type FooResult = typeof foo<number>()
unfortunately does not compile. The following code is about as close as you can get:
const __dummy = (true as false) || foo<number>();
type FooResultNumber = typeof __dummy; // {bar: number}
This introduces a dummy variable in your runtime code. The (true as false) || expression
construct uses a type assertion to lie to the compiler. The compiler thinks you are doing false || expression
, the type of which will be the same as the type of expression
. What you are really doing at runtime is true || expression
which short-circuits, returning true
without ever evaluating expression
. This means that foo()
never gets called at runtime despite being in the code.
Another way to pretend to call foo()
is with a dummy class... you will never instantiate the class but it lets the compiler reason about types:
class __FooRunner<T> {
result = foo<T>();
}
type FooResult<T> = __FooRunner<T>["result"];
type FooResultNumber = FooResult<number>; // {bar: number}
Again, this puts some junk in your runtime code, which may or may not be acceptable depending on your use cases.
Okay, hope that helps; good luck!
Upvotes: 1