4

I'd like to be able to define a type that takes in a generic parameter (that itself extends a type with 2 generic parameters) and define its constraints by using the nested generic parameters.

// Boiler plate for example setup:
type NodeCallback<T> = (err?: Error | void, result?: T) => void
type Handler<I, R> = (event: I, callback: NodeCallback<R>) => void
type StrToNumHandler = Handler<string, number>

// I end up having to do this:
type WorkaroundAsyncHandler<T extends Handler<I, R>, I, R> = (event: I) => Promise<R>
type WorkaroundStrToNumHandler = WorkaroundAsyncHandler<StrToNumHandler, string, number>

// I'd like to be able to just write this:
type AsyncHandler<T extends Handler<I, R>> = (event: I) => Promise<R> // This is a compiler error. Not sure how to write this in a valid way.
type AsyncStrToNumHandler = AsyncHandler<StrToNumHandler> // This is the line I'd ultimately like to write

The workaround I have compiles, but if I'm supplying the values for I and R, there isn't any value in supplying the Handler, which I'd like to be able to do.

1 Answer 1

1

You can get pretty close with conditional types and type inference in conditional types

type AsyncHandler<T> = T extends Handler<infer I, infer R> ? 
                             (event: I) => Promise<R> 
                          :  never
;

type AsyncStrToNumHandler = AsyncHandler<StrToNumHandler> 
// inferred as AsyncStrToNumHandler = (event: string) => Promise<number>

The downside is that your type alias should provide some type even if T is not actually Handler. The usual solution is to return never type. But the code that uses such alias can behave unexpectedly at compile time when it receives never type.

Sign up to request clarification or add additional context in comments.

1 Comment

Ah, interesting! Would this be solvable by adding an intersection of a non-never type? I expect that would strictly make any T that does not extend Handler a compilation error instead of propagating a never type along.

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.