枚举作为泛型中约束参数的不一致行为

时间:2015-04-09 17:33:23

标签: enums typescript

为什么无法将number扩展到number的内容?

这是一个简单的例子,我试图将枚举作为通用参数传递给函数。

enum Ev {A, B}

function fun<E extends number>(x: {[ix: number]: any}, e: E)
{
    return x[<number>e]
}

// no error here, so I assume is true that `Ev extends number`
fun({0:0}, Ev.A)

某些类型extends number似乎有点不一致,但在尝试将其强制转换为number时出现此错误:

  

两种类型&#39; E&#39;也不输入&#39; number&#39;可分配给另一个。

编辑:这是几乎相同的示例,但使用的是类而不是number(此编译没有错误):

class A {}

function fun<E extends A>(x: {[ix: number]: any}, e: E)
{
    return x[<A>e]
}

2 个答案:

答案 0 :(得分:2)

原始类型不能继承,因为有些类型具有需要特殊实例的特殊“能力”,而创建新的派生对象会阻止该能力。例如,无法为新的自定义派生对象调用字符串构造函数,因此无法将其应用于用户实例。这就是为什么没有从数字或其他任何东西继承的原因。

答案 1 :(得分:0)

  

为什么不可能将数字扩展到数字?

瑞安在this issue中指出,这似乎是一种语言中的错误;但请注意,这种形式的约束仅在函数的返回类型是类型参数的约束时才有用。例如:

function f<T extends number>(input: T) : T { return input; }
var t = f(Ev.A); // t : Ev

您提供的函数中的约束问题是它不会阻止传入数值。由于无法约束枚举成员,因此您也可以使用参数约束来定义函数:

function fun(x: {[ix: number]: any}, e: number)
{
    return x[e];
}

你这样做的抱怨是它不是自我记录代码。我会说最好给你的函数一个描述性名称来说明它的意图,而不是依赖于除了number约束之外没有约束优势的泛型。还要记住,在调用函数时,没有办法强制开发人员编写通用部分。他们可以轻松编写fun({0:0}, Ev.A)而不是fun<Ev>({0:0}, Ev.A)