59

Attempting to reduce boilerplate, I'm declaring some sort of generic function interface as a type. Then I want to declare a const of such type. So, why typescript assumes that foo declaration is legit and bar is not? Aren't these declarations practically identical? Is typescript lacking simple feature or am I missing some details? Is there any workarounds, if I do not want explicitly repeat FunctionType interface?

type FunctionType<TValue> = (value: TValue) => void;

const foo = <TValue>(value: TValue): void => {
}

//const bar: FunctionType<TValue> = (value) => { // Cannot find name 'TValue'
//}
Erik Philips
  • 53,428
  • 11
  • 128
  • 150
idementia
  • 851
  • 1
  • 6
  • 12

2 Answers2

71

There is a difference between a generic type that happens to be a function and a type that is a generic function.

What you defined there is a generic type that is a function. This means that we can assign this to consts that have the generic types specified:

type FunctionType<TValue> = (value: TValue) => void;
const bar: FunctionType<number> = (value) => { // value is number
}

To define a type that is a generic function we need to put the type parameter before the arguments list

type FunctionType = <TValue>(value: TValue) => void;
const bar: FunctionType = <TValue>(value) => { // generic function
}
Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357
  • @Hyster a variable can't be generic, so I am unsure what you are asking ... – Titian Cernicova-Dragomir Dec 01 '19 at 17:02
  • 1
    Take a look at this example: `const genericFunction = createGenericFunction()` - the `createGenericFunction` returns a generic function (xD) and I would like to be able to write a type for the `genericFunction` constant and keep it's generic. Take a look at ma answer below. – Hyster Dec 02 '19 at 07:37
  • 1
    Note that `(value ...` in the above example needs to be `(value ...`, in the context of JSX in React (or elsewhere), in order to prevent the generic type specification from being seen as a tag. – MikeBeaton Nov 24 '22 at 14:29
25

I have been trying to solve the same problem, which occurs especially when I'm using higher order functions (or React components) returning other generic functions (or components). I've found following solution:

interface GenericFunctionType {
    <T>(x: T): string
}

const genericFunction: GenericFunctionType = (x) => `doSomething with X ${x}`
Hyster
  • 646
  • 5
  • 15