Typescript 推断的泛型类型在条件类型中是未知的

Posted

技术标签:

【中文标题】Typescript 推断的泛型类型在条件类型中是未知的【英文标题】:Typescript inferred generic type is unknown in conditional type 【发布时间】:2020-09-22 15:01:46 【问题描述】:

我无法理解为什么data 属性在createRoute 的参数中没有正确推断为FeatureFlagData。基本上我想要实现的是根据canActivate 数组中的项目(因为它实现了通用GuardWithData),在createRoute 参数中推断data 的类型。我在这里想念什么?另外,有没有更好的方法来实现同样的目标?

下面是一些示例代码:

interface Guard 
    canActivate: () => boolean


export interface GuardWithData<D> extends Guard 
  data?: D;


export type DataType<T> = T extends GuardWithData<infer D> ? D : unknown;

class FeatureFlagGuard implements GuardWithData<FeatureFlagData> 
    canActivate()  return true; ;


interface Route 
    canActivate: any,
    data?: object


interface FeatureFlagData 
    featureFlag: string;


type ExtractGuardData<A extends Route> = A extends 
    canActivate: GuardWithData<infer U>,

  ? Route &  data: U 
    : never;

function createRoute<U extends Route>(route: ExtractGuardData<U>) 
  return route;


createRoute(
    canActivate: FeatureFlagGuard,
    data:  // <-- This type is to unknown, rather than the expected FeatureFlagData
)

【问题讨论】:

我没有遵循您为什么期望data 被推断为FeatureFlagData 类型的逻辑。你能解释一下你为什么会这样吗? 我希望当我调用createRoute 时,Typescript 能够推断出ExtractGuardData 中的U,进而也推断出GuardWithData 中的泛型类型,我以后可以用于创建组合类型(或交集类型)Route &amp; data: U ExtractGuardData),其中类型U 被推断为与GuardWithData(又名FeatureFlagData)中的D 相同。我怀疑我在这里做了一些根本错误的事情(或者至少有错误的期望),但我无法弄清楚我正在寻找什么或如何获得我正在寻找的行为。 【参考方案1】:
interface Guard 
    canActivate: () => boolean

这意味着具有属性canActivate 的对象是一个布尔函数。您将FeatureFlagGuard 传递给createRoute 的方式,看起来您希望FeatureFlagGuard 成为布尔函数,而不是具有canActivate 属性的对象。

interface Guard 
  (): boolean


export interface GuardWithData<D> extends Guard 
  (data?: D): boolean;


const FeatureFlagGuard: GuardWithData<FeatureFlagData> =
  (data?: FeatureFlagData) => true;

interface Route<D> 
  canActivate: GuardWithData<D>,
  data?: D


interface FeatureFlagData 
  featureFlag: string;


function createRoute<D>(route: Route<D>) 
  return route;


createRoute(
  canActivate: FeatureFlagGuard,
  data: 
)

【讨论】:

对,我可能不太清楚Route 中的canActivate 只是一个命名约定,恰好与Guard 接口中的require 方法canActivate 同名。 我必须遵守Guard 接口,但仍然可以通过让我的Guard 扩展给定的@987654336 来指定createRoute 参数中data 属性的类型@。所以底层框架(在这种情况下是Angular)期望createRoute中的canActivate属性是Guard类型(在我最初的问题中定义)。因此,我可以控制/修改的唯一部分是 GuardWithDataFeatureFlagGuardExtractGuardDataFeatureFlagData,这有意义吗?

以上是关于Typescript 推断的泛型类型在条件类型中是未知的的主要内容,如果未能解决你的问题,请参考以下文章

来自接口实现的 Typescript 泛型推断

TypeScript 条件类型的映射与受约束的泛型不同吗?

为啥 TS 中的泛型接口不能正确推断类型?

TypeScript:使用可变元组类型进行依赖类型推断

条件类型与泛型类型的推断方式不同

typescript :具有原始类型约束的泛型类型