2

I have a generic interface

export interface Method<T> {
    (answer: T): T;
}

I want to create an interface where I have fn function

interface Wrapper {
    fn: <T,>(a: T ) => T
}

but instead of manually writing the function type I want to use the interface

interface MethodWrapper {
   fn: Method
}

I want the fn to be generic at fn level not at the interface level. Is it possible?

ts-playground link

6
  • Does that mean you do not want to pass a generic type into MethodWrapper? Commented Aug 5, 2022 at 10:51
  • Yes, I don't want to do; interface MethodWrapper<T> {fn: Method<T>} Commented Aug 5, 2022 at 10:54
  • 1
    Alright. I think it's not possible to achieve your desired result then, but hopefully somebody else has another idea and can solve this. I for one think it is not possible. Commented Aug 5, 2022 at 10:55
  • 1
    TypeScript lacks the expressiveness to convert Method<T> into Wrapper programmatically. You'd need something like generic values as requested in ms/TS#17574 to do that. But the type <T,>(a: T)=>boolean is unnecessarily generic anyway, it is equivalent to (a: unknown)=>boolean as shown here. Could you modify your example so that the generic is required (e.g., <T,>(a: T) => T) like this? Once you do that I could write up an answer explaining why this isn't possible. Commented Aug 5, 2022 at 16:19
  • 1
    @jcalz updated the comment. Commented Aug 7, 2022 at 22:21

2 Answers 2

2

TypeScript's type system lacks the expressiveness to programmatically transform Method<T> into Wrapper. You'd need to move the scope of the generic type parameter T around in ways that can't be done.

If TypeScript had generic values as requested in microsoft/TypeScript#17574, then you might be able to say something like:

// Invalid TypeScript, don't do this
interface Wrapper {
  fn: forall T. Method<T>;
}

or

// Invalid TypeScript, don't do this
interface Wrapper {
  fn: <T> Method<T>;
}

But it doesn't so we can't.


You can almost do it the other way around and define Method<T> in terms of Wrapper, using instantiation expressions. I say "almost" because it requires that you drop down to the type level and acquire (or pretend to acquire) a value wrapper of type Wrapper before lifting back up to the type level. Like this:

declare const wrapper: Wrapper; // pretend to have this

type Method<T> = typeof wrapper.fn<T> // instantiate fn with <T>
// type Method<T> = (a: T) => T

Depending on your use case that may or may not be helpful.

Playground link to code

Sign up to request clarification or add additional context in comments.

Comments

0

Not sure I understand your question fully, but guessing from your TS playground you need to pass the type of the generic:

interface MethodWrapper {
   fn: Method<T> // T should be the type you want fn to receive
}

3 Comments

Won't work, ts would just say Cannot find name 'T'.(2304)
Of course, you need to replace T with the actual type you want to use. Can you include an example of how you'd like to use such thing?
The whole question is can I do it dynamically, i.e the invoker decides what is the type of T

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.