TypeScript中的通用类型参数推断优先级

时间:2016-04-25 08:24:52

标签: generics typescript decorator

我有以下class decorator factory接受初始化函数作为其参数。在这个initializer函数中,我想返回一个对应于所涉及的类类型(或派生类型)的实例:

function JsonObject<T>(initializer: (json: any) => T) {
    return function (target: { new (...args: any[]): T }) {
        // ...
    }
}
@JsonObject(function (json) {
    return new Animal();
})
class Animal {
    name: string;
}

返回确切类的实例(如上所述)可以正常工作,但是......

短版

返回派生类的实例不是。我可以返回 base 实例,但不能返回派生的实例。例如,我无法返回Cat

@JsonObject(function (json) {
    return new Cat(); // Error.
})
class Animal{
    name: string;
}

class Cat extends Animal {
    color: string;
}

......即使Cat 是动物。但是,对于猫来说,我可以返回 Animal 而不是Cat(这是一个错误,因为动物不一定是猫):

@JsonObject(function (json) {
    return new Animal(); // OK, but it shouldn't be
})
class Cat extends Animal {
    color: string;
}

长版

JsonObject装饰工厂

JsonObject函数类似于具有泛型类型参数T的函数,接受回调函数返回T作为其参数,并返回接受a的函数返回T 的newable类型。后者(返回的函数)显然是class decorator本身。

编译器不允许我 - 例如 - 从这个initializer函数(或任何其他不匹配类型)返回一个字符串,这应该是应该的。

子类型问题

但是,当使用子类型时,上述类型签名的行为完全相反:从initializer函数我可以返回 base 类型,但不能返回派生< / em> type - 在两步继承模式的中间类上使用时发生以下错误:

@JsonObject(function (json) {
    // Test case: return a base type.
    return new Animal(); // OK, but it shouldn't be: an 'Animal' is not a 'Cat'
})
@JsonObject(function (json) {
    // Test case: return an exact corresponding type.
    return new Cat(); // OK, as it should be
})
@JsonObject(function (json) {
    // Test case: return a derived type.
    return new Kitty(); // <-- Error, but it should be OK, a Kitty *is* a Cat
})
class Cat extends Animal {
    color: string;
}

class Kitty extends Cat {
    cutenessFactor: number;
}
  

错误:输入&#39; Cat&#39;不能分配给&#39; Kitty&#39;。物业&#39; cutenessFactor&#39;类型&#39; Cat&#39;

中缺少

我相信我已经确定了错误的起源,它是由编译器在推断泛型时引起的:泛型类型参数T是从&#34; T&#34推断出来的; initializer: (json: any) => T中,这意味着错误是由具有泛型类型Kitty的JsonObject函数引起的,Cat显然不能分配给它,因此该类在这种情况下,不能在Cat上使用装饰器。

我希望这样,T可以从&#34; return&#34;中推断出来。类型target,这将解决我的问题。我怎么能做到这一点?

当然,当我明确指定泛型类型参数时,它可以完美地工作(但这会带来多余的信息):

@JsonObject<Cat>(function (json) {
    return new Kitty(); // OK, since type 'Kitty' is assignable to type 'Cat'
})
class Cat extends Animal { }

1 个答案:

答案 0 :(得分:0)

你的意思是链接装饰者还是你的意思是这样:

zPosition

如果你的意思是上面^它编译得很好