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
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.
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);
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