【问题标题】:How can I write a generic function that uses the type of an enum member instead of the enum itself?如何编写一个使用枚举成员类型而不是枚举本身的通用函数?
【发布时间】:2018-03-26 02:09:31
【问题描述】:

TypeScript documentation on enums 说:

枚举成员也可以成为类型!

我想要一个函数,它接受一个作为枚举成员的通用值并使用特定枚举成员的类型。

我看到我可以使用枚举成员作为类型:

enum Kind {
    Apple,
    Banana,
}

type Example1 = Kind.Apple;

我可以在泛型类型上下文中使用枚举成员:

interface Wrapper<K> {
    kind: K;
}

type Example2 = Wrapper<Kind.Apple>;

当我将枚举成员传递给函数时,它会失去它是特定枚举成员的事实,而是将其设为父枚举类型:

const returned = <K>(kind: K): Wrapper<K> => ({
    kind,
})

const theValue = returned(Kind.Apple);

// Type 'Kind' is not assignable to type 'Kind.Apple'.
const butNot: Example2 = theValue;

Playground

【问题讨论】:

  • 这是对类型推断的抱怨吗?如果是这样,您的期望可能有点高... :) 您始终可以手动传入泛型类型:returned&lt;Kind.Apple&gt;(Kind.Apple)
  • 另一种解决方法是编写const returned = &lt;K extends Kind&gt;(kind: K): Wrapper&lt;K&gt; =&gt; ({ kind, }),但这使得returned 仅适用于Kind 子类型

标签: typescript generics enums


【解决方案1】:

您可以在调用 returned 时显式指定泛型类型:

enum Kind {
    Apple,
    Banana,
}

interface Wrapper<K> {
    kind: K;
}

const returned = <K>(kind: K): Wrapper<K> => ({
    kind,
})

const theValue = returned<Kind.Apple>(Kind.Apple);

const thisWorksNow: Wrapper<Kind.Apple> = theValue;

【讨论】:

    【解决方案2】:

    kind参数类型从Kind.Apple扩大到Kind的原因在https://github.com/Microsoft/TypeScript/pull/10676中有说明:

    在调用表达式的类型参数推断期间推断的类型 对于类型参数,T 被扩展为其扩展的文字类型,如果:

    • 对 T 的所有推断都是针对特定参数类型中 T 的顶级出现进行的,并且
    • T 没有约束或其约束不包括原始类型或文字类型,并且
    • T 在推理期间已修复,或者 T 未出现在返回类型的顶层。

    如果如第二个项目符号所述,为泛型参数T 添加约束,它将开始推断特定的文字类型。这样做的代价是它使returned 仅适用于Kind 的子类型。

    enum Kind {
        Apple,
        Banana,
    }
    
    interface Wrapper<K> {
        kind: K;
    }
    
    const returned = <K extends Kind>(kind: K): Wrapper<K> => ({
        kind,
    })
    
    const theValue = returned(Kind.Apple);
    
    const thisWorksNow: Wrapper<Kind.Apple> = theValue;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-08
      • 2012-11-05
      • 1970-01-01
      • 2020-12-16
      • 2014-10-08
      相关资源
      最近更新 更多