搜索词
基类表达式不能引用类类型参数
建议
目前在 TypeScript 中可以通过函数动态生成基类(
function prop<T>(): T {
// implementation detail doesn't matter
return null as any;
}
function createDynamicClass<T>(_props: T): { new(): T} {
// implementation detail doesn't matter
return null as any;
}
// without generics on the main class all is fine
class C2 extends createDynamicClass({x: prop<number>()}) {
setX(x: number) {
this.x = x
}
}
const c2 = new C2()
c2.x = 20
c2.setX(30)
):
并且当基类是一个具有泛型类型的“纯”类时,也可以重用泛型:
class Base<T> { x: number }
class Child<T> extends Base<T> {}
然而,目前对于生成动态类的函数来说,无法重用子类的类型:
// error: Base class expressions cannot reference class type parameters
class C3<T> extends createDynamicClass({x: prop<T>()}) {
setX(x: T) {
this.x = x
}
}
const c3 = new C3<number>()
c3.x = 20
c3.setX(30)
有一个(某种程度上不太美观)的解决方法,即将生成子类的过程封装在一个函数中并使用其结果:
function generateC4<T>() {
return class extends createDynamicClass({ x: prop<T>() }) {
setX(x: T) {
this.x = x
}
}
}
const C4 = generateC4<number>()
const c4 = new C4()
c4.x = 20
c4.setX(30)
但这相当不美观,并且在实际上不需要每个泛型时(仅用于类型检查),会为每个泛型生成一个新的类。
该提案基本上是解除这个约束,允许它被使用(就像可以轻松地用于纯类一样)。
使用案例
目前在 mobx-keystone 中使用这样的模式(一个生成动态基类的函数)来生成模型:
class Point extends Model({
x: prop<number>(),
y: prop<number>(),
}) {
@modelAction
setXY(x: number y: number) {
this.x = x
this.y = y
}
}
const numberPoint = new Point({x: 10, y: 20})
但是为了支持泛型,用户不得不采用这种工厂模式:
class Point<T> extends Model({
x: prop<T>(),
y: prop<T>(),
}) {
@modelAction
setXY(x: T, y: T) {
this.x = x
this.y = y
}
}
const numberPoint = new Point<number>({x: 10, y: 20})
这远非理想(而且这只是为了正确设置类型)。
示例
参见上面
检查清单
我的建议满足以下指导原则:
- 这不会对现有的 TypeScript/JavaScript 代码造成破坏性更改
由于它只是解除了一个当前不允许的约束,所以没有当前的代码可以使用它。
- 这不会改变现有 JavaScript 代码的运行时行为
运行时行为完全相同,只是解决了类型检查问题。
- 这可以在不根据表达式的类型发出不同的 JS 的情况下实现
- 这不是一个运行时特性(例如库功能、JavaScript 输出非 ECMAScript 语法等)
- 这个特性将与 TypeScript's Design Goals 的其他部分保持一致。
4条答案
按热度按时间nzk0hqpo1#
我仅阅读了描述的前半部分。然而,这是否解决了你的问题?
7gcisfzg2#
你好,感谢查看!遗憾的是它没有。我只是更改了理论示例,以便它们更好地匹配使用案例。
实际案例依赖于动态类函数的类型推断才能工作。
1rhkuytd3#
如果TypeScript支持这个功能,将会非常有帮助。是否有人对此感兴趣并/或在实现它方面取得了进展?有任何未解决的问题吗?
moiiocjp4#
我也面临这个问题。