Unfortunately, TypeScript has no direct support for higher kinded types (HKTs) of the sort you intend A
to be. And you cannot refer to Id
without immediately specifying its type parameter like Id<T>
for some T
. See microsoft/TypeScript#1213 for a longstanding, open feature request for higher kinded types. That issue does list out some ways that HKTs can be simulated/emulated in TypeScript, but nothing nice enough that I'd really recommend it.
For example, you can do something like this where you explicitly register every higher-kinded type you care about by merging it into an interface declaration:
type Id<T> = T;
interface HKTRegistry<T> { Id: Id<T> };
type List<T> = T[];
interface HKTRegistry<T> { List: List<T> }
And then you could use it like this:
const f = <A extends HKT, B>(a: Specify<A, B>, b: B): [Specify<A, B>, B] => [a, b];
const id = f<"Id", number>(1, 2);
const hmm = f<"List", number>([1], 2);
where HKT
and Specify
are defined like this:
type HKT = keyof HKTRegistry<any>
type Specify<H extends HKT, T> = HKTRegistry<T>[H];
Playground link to code
But it's clunky and doesn't capture things like constrained type parameters and it's hard to infer an HKT this way. As I said, it's not really in a place I'd recommend for any production code.