TypeScript: how can I use a templated type without specifying the template parameter?

Viewed 435

Minimal working example:

type FuncType<T> = (a: T) => T;

let f1: FuncType<T>; // does not compile
let f2: <T>(a: T) => T; // compiles

The problem is that FuncType is not defined by me, but comes from a library. It is also way more complex than the example above. I would like to use the templated type exported from the library, instead of having to re-declare it myself (as I do when I annotate f2).

Is it even possible? If not, do you know why not?

Thanks for any input, I cannot find anything on this topic

1 Answers

You can't type a variable as an un-instantiated generic type.

The reason <T>(a: T) => T works is because that is a generic function. FuncType<T>, as defined is a generic type that happens to be a function. The difference being that for a generic function the type parameter is decided at call site (for each call) while for a generic type the type is decided when you declare the variable and is unaffected by subsequent calls.

type FuncType<T> = (a: T) => T;

declare let f1: FuncType<number>;
f1(1) // ok, T is number
f1("1") // not ok, T is still number
declare let f2: <T>(a: T) => T; 
f2(1) // ok, T is number 
f2("1") // also ok, T is now string

Playground Link

If you want to represent any instantiation of FuncType your best bet is FuncType<any>. But you will have to live with the associated unsafety. (unknow and never won't work here as FuncType is invariant in T, they would work for type FuncType<T> = () => T and type FuncType<T> = (a: T) => void respectively)

Related