0

According to TypeScript handbook, there is a type inferring in function type declaration. But when I introduce generic type into function declaration, the type inferring somehow not working. I have to explicitly write the type. Why the type inferring is not working when there is generic type?

const fn1: (x: number, y: number) => number = (x, y) => {
  // working
  return x + y;
}
const fn2: <T>(x: number, y: number) => Promise<T> = <T>(x, y) => {
  // not working, although ws hints these parameters' type is number
  ...use type T somewhere...
  ...x + y;
  ...
}

error screen shot

Edit: Thank you for the comment. But my question is different.

const fn1: (x: number, y: number) => number = (param1, param2) => {
  // typescript will infer the type of param1 and param2 is number
  return param1 + param2;
}
const fn2: <T>(x: number, y: number) => number = <T>(param3, param4) => {
  // I think typescript will infer the type of param3 and param4 is number
  // but with strict flag true (noImplicitAny), there is a compile error says param3 and param4 is type any
  // why adding generic type to function will cause type inferring not working?
  return param3 + param4;
}

Edit 2: Here is the actual code from the project

type Request = <T>(method: Method, url: string, params?: Record<string, unknown>) => Promise<T>;
const request: Request = async <T>(
  // because I have declare the parameters type in type Request
  // why I have to declare the type again here for the parameters?
  // if I omit types here, typescript thinks these params are 'type any'
  method: Method, url: string, params: Record<string, unknown> = {},
) => {
  const fetchConfig: RequestInit = {
    method,
    credentials: 'same-origin',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
    },
  };
  let targetUrl = url;

  switch (method) {
    case Method.Get:
    case Method.Delete:
      targetUrl += qs.stringify(params, { addQueryPrefix: true, arrayFormat: 'comma' });
      break;
    case Method.Post:
      fetchConfig.body = JSON.stringify(params);
      break;
    default:
  }

  const resp = await fetch(targetUrl, fetchConfig);
  // I need to use generic type T here
  const respJson = await resp.json() as T;
  if (resp.status >= 200 && resp.status < 300) {
    return respJson;
  }
  if (resp.status === 401) {
    globalThis.history.replaceState(undefined, '', RouteURL.adminLogin);
  }
  const newError = new Error('Request failed');
  Object.assign(newError, { json: respJson });
  throw newError;
};
puuuudding
  • 71
  • 7
  • Does this answer your question? [What is the syntax for Typescript arrow functions with generics?](https://stackoverflow.com/questions/32308370/what-is-the-syntax-for-typescript-arrow-functions-with-generics) – hackape Sep 25 '20 at 11:33
  • See also: https://github.com/Microsoft/TypeScript/issues/4922 – hackape Sep 25 '20 at 11:33
  • If you're hoping `param3`/`param4` can be generic, you are forced to drop all assumptions about their type when you use them. This means that adding `param3 + param4` can't possibly work. They could be anything. – spender Sep 25 '20 at 12:52
  • What's not clear here is the actual problem you are trying to solve. Spell it out in your question, and you might be offered better guidance. – spender Sep 25 '20 at 12:54

1 Answers1

0

Syntactically, your problem is the <T> in <T>(x,y) after the =. You've already declared the type before the = as <T>(x: number, y: number) => Promise<T>. Everything to the right of the = is just an assignment so typing is not appropriate there.

What's a little less clear to me is what kind of inference you are hoping for. Do you want the value in the promise to have the same type as the arguments? In that case you should type it as: <T>(x: T, y: T) => Promise<T>

sam256
  • 1,291
  • 5
  • 29