3

Is it possible in Typescript to implement an infinite Array (not a Tuple) with a type that depends on the previous element of the array?

Here's some pseudo-typescript code to give an example:

class B<T, U> {}

function foo<X, Y>(...args: [B<X, Z0>, B<Z0, Z1>, B<Z1, Z2>, ..., B<ZN, Y>]) {}

foo<string, number>(new B<string, number>, new B<number, boolean>, new B<boolean, number>); // Correct
foo<string, number>(new B<string, number, new B<number, boolean>); // Incorrect
foo<string, number>(new B<string, number>, new B<boolean, number>); // Incorrect

What should I replace the "[B<X, Z0>, B<Z0, Z1>, B<Z1, Z2>, ..., B<ZN, Y>]" with to make this work? Is this even possible?

Thank you!

1
  • 1
    I'm inclined to close this as a duplicate of this question but the question here isn't quite specific enough for me to tell what's going on. Your example B is an empty class with unused type parameters, thus it is impossible to have any code that accepts. say, B<string, number> while rejecting B<boolean, number>, since they are identical types equal to {}. `.Please consider modifying the code so as to constitute a minimal reproducible example that can be dropped into a standalone IDE to demonstrate the issue to others. Commented Dec 19, 2020 at 19:24

1 Answer 1

2

I recently encountered a similar problem. My problem involved creating a long pipe of streams. The output of stream i had to be the input of stream i+1, etc. I solved it like this:

type OmitFirst<T extends any[]> = T extends [any, ...infer R] ? R : never
type GetValueOrDefault<Thing, Key, Default = never> = Key extends keyof Thing ? Thing[Key] : Default
type Pipe<Start, Finish, Inputs extends [Start, ...any[]], Outputs extends any[] = OmitFirst<Inputs>> = {
    [I in keyof Inputs]: DuplexConstructor<Inputs[I], GetValueOrDefault<Outputs, I, Finish>>
}

export function pipe<F, L, P extends [F, ...any[]]>(
    ...streams: [ReadableConstructor<F>, ...Pipe<F, L, P>, WritableConstructor<L>]
): Writable {
    const source = streams[0]
    const duplexes = streams.slice(1, -1) as Pipe<F, L, P>
    const sink = streams[streams.length - 1] as WritableConstructor<L>

    let tail = readable(source)
    duplexes.forEach((dp) => (tail = tail.pipe(duplex(dp))))
    return tail.pipe(writable(sink))
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.