I'm working on building a Typescript .ds file for reactive-coffee (http://yang.github.io/reactive-coffee/api.html), and I'm running into trouble trying to figure out the type signature for the flatten function. An example:
flatten(rx.array([1, [2, 3], rx.cell(4), rx.array([rx.cell([5, rx.cell(6)])])]))
// -> [1,2,3,4,5,6]
flatten([1, [2, 3], rx.cell(4), rx.array([rx.cell([5, rx.cell(6)])])])
// -> [1,2,3,4,5,6]
The question I'm running into trouble with is: what is the correct Typescript type signature for xs? So far I've come up with something like this:
interface NestableCell<T> extends ObsCellInterface<T | NestableCell<T>> {}
type Flattenable<T> = (
Array<T| NestableCell<T | Flattenable<T>> | Flattenable<T>> |
ObsArrayInterface<T | NestableCell<T | Flattenable<T>> | Flattenable<T>>
)
function flatten<T>(xs:Flattenable<T>) => ObsArrayInterface<T>
ObsCellInterface and ObsArrayInterface are typed versions of RC's ObsCell and ObsArray objects, respectively.
Unfortunately, Typescript does not allow recursive types, only recursive interfaces. And at this point I'm really not sure how to convert that type to an interface.
The following seems to work, though I haven't yet had time to prove that it satisfies all possible cases:
interface NestableCell<T> extends ObsCell<T | NestableCell<T>> {}
interface FlattenableRX<T> extends ObsArray<
T |
NestableCell<T | FlattenableJS<T> | FlattenableRX<T>> |
FlattenableJS<T> |
FlattenableRX<T>
> {}
interface FlattenableJS<T> extends Array<
T |
NestableCell<T | FlattenableJS<T> | FlattenableRX<T>> |
FlattenableJS<T> |
FlattenableRX<T>
> {}
export type Flattenable<T> = FlattenableRX<T> | FlattenableJS<T>
Using two mutually recursive interfaces appears to avoid the worst complications from having to support both primitive and reactive arrays.
As I said, I cannot yet prove that this works, but it at least seems plausible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With