TypeScript 为基本约束类型参数定义可分配关系

ne5o7dgx  于 6个月前  发布在  TypeScript
关注(0)|答案(6)|浏览(55)

规范没有在赋值兼容性中定义任何情况,其中 S 是一个约束为基本类型的类型参数,而 T 是相同的基本类型。
这导致了一些奇怪的错误,例如 T 不能分配给 number,尽管 T extends number:

enum E { A, B, C }
enum F { X, Y, Z }

function f<T extends number>(x: T[]): T {
    var y: number = x[0]; // Error, T is not assignable to number...??
} 

// f<T extends number> is useful:
var x = f([E.A, E.B]); // ok, x: E
var y = f([F.X, F.Y]); // ok, y: F
var z = f(['foo', 'bar']); // Error

另请参阅 http://stackoverflow.com/questions/29545216/inconsistent-behavior-of-enum-as-constrained-parameter-in-generic

guicsvcw

guicsvcw1#

如果不允许原始类型被扩展,那么编写 T extends number 有什么用处,为什么应该允许它?它似乎并没有限制语言中的任何内容。
总有人可以这样编写上面的函数,我认为这样更有意义:

function f(x: number[]) {
    var y: number = x[0];
}

或者我是不是漏掉了什么?

kknvjkwl

kknvjkwl2#

如果不允许原始类型被扩展,那么编写 T extends number 有什么用处,为什么应该允许?
请参阅原始帖子中的示例 var xvar yvar z。枚举成员是 number 的子类型,将函数输入的类型与其输出类型关联起来在限制函数可以处理的类型时是有用的。

oyt4ldly

oyt4ldly3#

好的,这很有道理。顺便说一下,可能有益于添加约束enumEnumMember的能力。

jecbmhm3

jecbmhm34#

不仅仅是原始类型,类型参数对其约束的不可分配性会带来问题;我也在联合体中遇到过这个问题。这里有一个真实的例子:

interface ComparableObject { compare(other: ComparableObject): number; }
type Comparable = number | string | ComparableObject;

function compare(a: Comparable, b: Comparable): number {
    // ...
}

function binarySearch<T extends Comparable>(array: T[], element: T) {
    // ...
    compare(array[i], element) // Error: T not assignable to Comparable
    // ...
}

类层次结构更糟:

class Column<T extends Comparable> {
    getValue(row: number): T { return; } // abstract
    render(value: T, node: HTMLElement) {} // abstract
    sort(rows: number[]) {
        // More errors here...
        return rows.sort((a, b) => compare(this.getValue(a), this.getValue(b)));
    }
}

// Yet another error here - and no way to hack around it with casts!
class FancyColumn<T extends Comparable> extends Column<T> { /* ... */ }

我不明白为什么类型参数的子类型/可分配性需要为每种约束(对象、原始类型、联合体、另一个类型参数等)有单独的规则 - 似乎只需要一个通用规则就足够了:“S是一个类型参数,且S的约束是T的子类型或可分配给T。”

vcirk6k6

vcirk6k66#

@jeffreymorlan ,工会问题由#2778解决。但正如你提到的,似乎很愚蠢的是,每种约束都必须得到考虑。可能更正确的做法是递归地检查S的基本约束是否可以分配给T。

相关问题