【问题标题】:TypeScript: how to extract the generic parameter from a type?TypeScript:如何从类型中提取泛型参数?
【发布时间】:2023-04-02 21:00:02
【问题描述】:

假设我有一个像 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&lt;typeof x&gt;

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

【问题讨论】:

  • 你为什么要这样做?你会用这种类型做什么?你不能在不知道类型的情况下分配任何东西,即:const y : GetPropsType&lt;typeof x&gt; = ???
  • 不是 100% 肯定,但我想说在运行时这样做的唯一方法是首先获取该类型的实际对象,然后对其运行 typeof。在这种情况下,获取你的 react 组件的 props。
  • 嘿,您找到了完美的解决方案吗?我需要在 Vue.js 中做同样的事情

标签: typescript


【解决方案1】:

你可以使用推断:

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

type extracted = extractGeneric<TypeWithGeneric<number>>
// extracted === number

Playground

【讨论】:

  • 是否有一个“通用”版本,您不需要知道实际的通用类?还是那不可能?我想“通用”提取泛型类型 ;-)
  • 我不认为现在这是可能的@Simon_Weaver,目前没有办法泛型引用类型构造,因为 Typescript 不支持 Higher Kindred Types。
  • 会优先于never 而不是null
  • 如何获得第 n 个泛型参数?
【解决方案2】:

您可以为此使用模式匹配:

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

【讨论】:

  • 这在某种程度上有效,谢谢。不幸的是,这意味着创建一个假常量,然后用typeof 引用它,所以我希望有更好的方法,但是我会尽我所能
  • 假常量仅用于演示目的。如果您好心告诉我们您的最终目标是什么,我们可以为您提供具体的解决方案。你掉进了xy problem的陷阱
【解决方案3】:

我想分享一个真实世界的例子来提取 R 泛型类型 MatDialogRef&lt;T, R = any&gt; 这是 Angular 材料的对话框。

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

export class DialogPleaseWaitComponent implements OnInit {

  constructor(@Inject(MAT_DIALOG_DATA) public data: DialogPleaseWaitModel,
              public dialogRef: MatDialogRef<DialogPleaseWaitModel, { timedOut: boolean }>) { 

  }

所以我想出了:

extractMatDialogResponse<T>

我让它在两种“模式”下工作,要么采用组件类型,要么采用 MatDialogRef 本身。所以我可以输入extractMatDialogResponse&lt;DialogPleaseWaitComponent&gt; 并返回{ 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 使用的机制相同,但演示了如何为特定用途制作“目标”提取器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-10
    • 2020-11-11
    • 2021-12-08
    • 2016-11-01
    • 2022-07-27
    相关资源
    最近更新 更多