[英]Typescript generic constraint that uses inferred method return type
我有这种情况:
abstract class AbstractClass<T> {
abstract getData(): T;
getBase(): Partial<T> {
return {};
}
}
interface Contract {
prop1: string;
prop2: string;
}
class Impl extends AbstractClass<Contract> {
get prop1() {
// some complex logic here
return '';
}
getBase() {
return {
prop2: 'foo'
}
}
}
我如何表达约束正确的AbstractClass
实现必须涵盖Contract
接口的所有属性 ? 简单的解决方案是Impl implements Contract
,但是我将不得不为没有复杂逻辑getter的所有属性复制声明。 所以能够使用推断类型的getBase()
实现会很高兴。 如果在Impl
本身上没有提供任何值或者作为推断返回类型getBase()
属性,则目标是产生编译时错误。 是原则上可以使用Typescript吗?
如果使getBase
abstract并指定返回必须是当前类和接口的属性的差异,那么如果属性不在getBase
或类的结果中,则会出现编译时错误:
abstract class AbstractClass<T, TThis> {
abstract getBase(): { [P in Exclude<keyof T, keyof TThis>]: T[P] };
}
interface Contract {
prop1: string;
prop2: string;
}
class Impl extends AbstractClass<Contract, Impl> {
get prop1() {
// some complex logic here
return '';
}
getBase() {
return {
prop2: ""
}
}
}
class ImplWrong extends AbstractClass<Contract, ImplWrong> {
get prop1() {
// some complex logic here
return '';
}
getBase() { // error Property 'getBase' in type 'ImplWrong' is not assignable to the same property in base type
return {
prop3: ""
}
}
}
你会发现,我必须通过一类本身作为一种类型argumentto的基类,使用this
类型不是解决方案的关键this
是从来没有完全清楚。
此外, getBase
必须至少返回Impl
和Contract
之间的差异,但它可以返回更多属性(typescript允许实现返回实现方法的超类型)。 因此,如果在类和返回的getBase
都有prop1
, getBase
它就不会出错。
另一个解决方案是为Impl
类添加约束,并保留getBase
返回类型:
abstract class AbstractClass<T> {
abstract getData(): T;
getBase(): Partial<T> {
return {};
}
}
interface Contract {
prop1: string;
prop2: string;
}
type ImplConstraint<T, I extends AbstractClass<T>> =
{ [n in Exclude<keyof T, keyof ReturnType<I['getBase']>>]: T[n] };
class Impl extends AbstractClass<Contract> implements ImplConstraint<Contract, Impl> {
get prop1() {
// some complex logic here
return '';
}
getBase() {
return {
prop2: 'foo'
}
}
getData(): Contract {
return {} as Contract;
}
}
class ImplWrong extends AbstractClass<Contract> implements ImplConstraint<Contract, ImplWrong> {
// Class 'ImplWrong' incorrectly implements interface
// 'ImplConstraint<Contract, Impl>'
// Property 'prop1' is missing in type 'ImplWrong'.
get prop11() {
// some complex logic here
return '';
}
getBase() {
return {
prop2: 'foo'
}
}
getData(): Contract {
return {} as Contract;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.