[英]Generic type parameter inference priority in TypeScript
我有以下類裝飾器 工廠接受初始化函數作為其參數。 在這個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;
}
返回確切類的實例(如上所述)可以正常工作,但是......
返回派生類的實例不會 。 我可以返回一個基本實例,但不能返回派生實例。 例如,我不能歸還一只Cat
:
@JsonObject(function (json) {
return new Cat(); // Error.
})
class Animal{
name: string;
}
class Cat extends Animal {
color: string;
}
......即使貓是動物。 然而,對於貓來說,我可以返回一只動物而不是貓(這是一種錯誤,因為動物不一定是貓)
@JsonObject(function (json) {
return new Animal(); // OK, but it shouldn't be
})
class Cat extends Animal {
color: string;
}
JsonObject
函數類似於具有泛型類型參數T
函數,接受返回T
作為其參數的回調函數,並返回接受返回T
的可更新類型的函數 。 后者(返回的函數)顯然是類裝飾器本身。
編譯器不允許我 - 例如 - 從這個initializer
函數(或任何其他不匹配類型)返回一個字符串,這是應該的。
但是,當使用子類型時,上述類型簽名的行為完全相反:從initializer
函數我可以返回基本類型,但不是派生類型 - 在2步的中間類上使用時會發生以下錯誤繼承模式:
@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;
}
錯誤:類型'Cat'不能分配給'Kitty'類型。 'Cat'類型中缺少屬性'cutenessFactor'。
我相信我已經確定了錯誤的起源,它是由編譯器在推斷泛型時引起的:泛型類型參數T
是從initializer: (json: any) => T
的“T”推斷的initializer: (json: any) => T
,這意味着錯誤是由具有通用類型Kitty
的JsonObject函數引起的, Cat
顯然不能將其分配給它,因此在這種情況下,類裝飾器不能用於Cat
。
我希望它能夠從“返回”類型的target
推斷出T
,這將解決我的問題。 我怎么能做到這一點?
當然,當我明確指定泛型類型參數時,它可以完美地工作(但這會帶來冗余信息):
@JsonObject<Cat>(function (json) {
return new Kitty(); // OK, since type 'Kitty' is assignable to type 'Cat'
})
class Cat extends Animal { }
你的意思是鏈接裝飾者還是你的意思是:
function JsonObject<T>(initializer: (json: any) => T) {
return function (target: { new (...args: any[]): T }) {
return null;
}
}
@JsonObject(function (json) {
return new Foo();
})
class Foo {
foo: string;
}
@JsonObject(function (json) {
// Test case: return an exact corresponding type.
return new Bar(); // OK, as it should be
})
class Bar extends Foo {
bar: string;
}
@JsonObject(function (json) {
// Test case: return a derived type.
return new Baz(); // Ok
})
class Baz extends Bar {
baz: string;
}
如果你的意思是上面^它編譯得很好
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.