简体   繁体   中英

How to infer generic type of a generic

I have an interface called Expression that through an OperatorExpression goes back to itself in like an infinite nesting structure.

Im passing in a generic that already has a generic and I would like to infer it.

I have the following interfaces:

type Expression<T, U = string> = (T extends Approval<U> ? Approval<U> : Condition<U>) | OperatorExpression<T, U>

interface OperatorExpression<U, T = string> {
   operands: Expression<T, U>[]
   // other stuff
}

interface Approval<T = string> {
   approver: T
   // other stuff
}

interface Condition<T = string> {
   id: T
   // other stuff
}

And then when I use the Expression with a generic that has a generic that is not string, I have to call it like this:

Expression<Approval<Types.ObjectId>, Types.ObjectId>

And I would like to be able to call it like this: Expression<Approval<Types.ObjectId>> , basically infer the second generic based on the generic of the first generic.

In my little ts knowledge I imagined to do something like this, but it complains because "S" does not exist:

type Expression<T extends (Approval<S> | Condition<S>), U = S> = (T extends Approval<U> ? Approval<U> : Condition<U>) | OperatorExpression<T, U>

How could I do this? Thank you


edit

Since this is now solved thanks @Meowster, I'll put down here his solution integrated in my use case

type InferType<T> = T extends Approval<infer E> | WorkflowCondition<infer E> ? E : never;

type R<T> = InferType<T>

 export type Expression<T, U = R<T>> =
    | (T extends Approval<U> ? Approval<U> : T extends WorkflowCondition<U> ? WorkflowCondition<U> : WorkflowApproval<U>)
    | OperatorExpression<T, U>
type Expression<T extends Approval | Condition> = T | OperatorExpression<T>

interface OperatorExpression<T extends Approval | Condition> {
   operands: Expression<T>[]
   // other stuff
}

interface Approval<U = any> {
   approver: U
   // other stuff
}

interface Condition<U = any> {
   id: U
   // other stuff
}

type E = OperatorExpression<Approval<number>>
type O = E['operands'] // Expression<Approval<number>>[]

or use infer syntax

type InferType<T> = T extends Approval<infer E> | Condition<infer E> ? E : never;

interface Approval<T = string> {
    approver: T
    // other stuff
 }
 
 interface Condition<T = string> {
    id: T
    // other stuff
 }

 type R = InferType<Approval<number>> // R = number

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM