Implement non-generic interface containing generic method

Viewed 69

I have the following interface, which contain generic method signature:

interface IFetcher {
  fetch<T>(): T;
}

I want to mock it in unit tests, so I tried:

const mockFetch: IFetcher = {
  fetch: (): T => {
    return {} as T;
  }
}

but I am getting the following error:

Cannot find name 'T'.

Other variants I tried:

const mockFetch: IFetcher = {
  fetch: <T>(): T  => {
    return {} as T;
  }
}

which leads to

Cannot find name 'React'.

and

const mockFetch: IFetcher = {
  fetch<T>: (): T => {
    return {} as T;
  }
}

which leads to

Type '() => () => any' is not assignable to type '() => T'. Type '() => any' is not assignable to type 'T'. 'T' could be instantiated with an arbitrary type which could be unrelated to '() => any'.

This works:

const mockFetch: IFetcher = {
  fetch: (): any => {
    return {};
  }
}

but I don't want to use any.

And this also works, but introduces another type:

interface A {
}

const mockFetch: IFetcher = {
  fetch:<A extends unknown>(): A => {
    return {} as A;
  }
}

What is the proper way to implement this interface, preserving type safety as much as possible?

1 Answers

In tsx files, <T> will be interpreted as the start of a JSX tag. You can add a , which will convince typescript this is a type parameter list not a JSX tag (trailing commas are allowed in type parameter lists)

const mockFetch: IFetcher = {
  fetch: <T,>(): T  => {
    return {} as T;
  }
}

Playground Link

Related