TypeScript:如何从类型中提取泛型参数?



>假设我有一个像React.ComponentClass<Props>这样的类型,我想引用Props部分,但它在我当前的上下文中未命名。

举例说明:

const x = makeComponent(); // typeof x = React.ComponentClass<Something>

在这种情况下,我可以使用typeof x但这并不能直接给我 访问Something类型。

我想要的是这样的东西:

type GetPropsType<C extends React.ComponentClass<P>> = P

这样我就可以提取Something类型GetPropsType<typeof x>

任何等价的东西都会很棒。

您可以使用推断:

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

操场

您可以使用模式匹配:

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

以为我会分享一个真实世界的例子来提取MatDialogRef<T, R = any>R泛型类型,即 Angular 材质的对话框。

我经常有这样的组件,其中输出"模型"是一个简单的接口,不太值得它自己的命名类型。

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

所以我想出了:

extractMatDialogResponse<T>

我让它在两种"模式"下工作,要么采用组件类型,要么采用 MatDialogRef 本身。所以我可以放extractMatDialogResponse<DialogPleaseWaitComponent>{ timedOut: boolean }回来:-(

是的 - 如果T是组件类型,则它要求dialogRef是属性的确切名称,并且它确实需要是公共的。

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;

也是的,这与 Xiv 使用的机制相同,但演示了如何为特定用途制作"目标"提取器。

最新更新