Let's say I have an interface A
:
interface A {
foo: number
bar: string
}
And I have a generic type Option
:
type Option<T> = {
map: () => T
}
Then I create a new interface B
from A
and Option
:
interface B {
foo: Option<number>
bar: Option<string>
}
How can I make this operation more general? Ie. The API I want is:
type B = Lift<A>
Where Lift
automatically maps each member of A
to an Option
. Note that A
can have any number of members, of any type.
How can I implement Lift
? If this is not possible in TypeScript, does anyone have a Scala/Haskell solution?
I haven't looked at TypeScript for a while (I think it was around version 1.0), so I can't really tell if it's there now.
What you want requires a type system feature called higher kinded types ; it allows one to construct types by passing them as arguments to type constructors, very much like function application, lifted to the type level.
You'll have to adjust A's definition in order to make this work. Here's how I'd achieve what you want in Haskell :
You are looking for higher-kinded types. Here it is in Scala:
You can use any second-order types e.g.:
But these will not compile:
Unfortunately, this has not yet made it into TypeScript but there is an open issue for it: https://github.com/Microsoft/TypeScript/issues/1213
Good news: With TypeScript 2.1.0, this is now possible via Mapped Types:
The opposite is also possible: