TypeScript: how to extract the generic parameter from a type?

后端 未结 3 1987
Happy的楠姐
Happy的楠姐 2020-12-01 20:56

Say I have a type like React.ComponentClass and I want to reference the Props part but it is unnamed in my current context.

To

相关标签:
3条回答
  • 2020-12-01 21:20

    Thought I'd share a real world example to extract the R generic type for MatDialogRef<T, R = any> which is Angular material's dialog box.

    I often have components like this, where the output 'model' is a simple interface that isn't quite worthy of its own named type.

    export class DialogPleaseWaitComponent implements OnInit {
    
      constructor(@Inject(MAT_DIALOG_DATA) public data: DialogPleaseWaitModel,
                  public dialogRef: MatDialogRef<DialogPleaseWaitModel, { timedOut: boolean }>) { 
    
      }
    

    So I came up with:

    extractMatDialogResponse<T>
    

    I made it work in two 'modes', either taking the component type or the MatDialogRef itself. So I can put extractMatDialogResponse<DialogPleaseWaitComponent> and get back { timedOut: boolean } :-)

    Yes - if T is the component type then it requires dialogRef to be the exact name of the property, and it does need to be public.

    type extractMatDialogResponse<T = MatDialogRef<any, any> | { dialogRef: MatDialogRef<any, any> }> = 
         T extends MatDialogRef<any, infer R> ? R :                                                                                                          
         T extends { dialogRef: MatDialogRef<any, infer R> } ? R : never;
    

    Also yes this is the same mechanism as used by Xiv, but demonstrates how to make a 'targeted' extractor for a specific use.

    0 讨论(0)
  • 2020-12-01 21:27

    You can use pattern matching for that:

    namespace React {
        export class ComponentClass<T> {}
    }
    
    function doSomethingWithProps<T>(x : React.ComponentClass<T>) : T {
        return null as T;
    }
    
    class Something {}
    let comp = new React.ComponentClass<Something>();
    const instanceOfSomething = doSomethingWithProps(comp);
    
    0 讨论(0)
  • 2020-12-01 21:36

    You can use infer:

    type TypeWithGeneric<T> = T[]
    type extractGeneric<Type> = Type extends TypeWithGeneric<infer X> ? X : never
    
    type extracted = extractGeneric<TypeWithGeneric<number>>
    // extracted === number
    

    Playground

    0 讨论(0)
提交回复
热议问题