搜索词
我在问题列表中搜索 "decorate abstract member",#20887 提到了这个问题,但已经关闭。
建议
能够装饰抽象函数及其参数。
用例
为了用 Typescript 实现一个类似 retrofit 的 http 请求库。从 retrofit 网站上的例子来看:
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
当我们将其翻译成 Typescript 时,由于编译后接口会被擦除,我们需要装饰一个抽象类。但是,
@MyAPI() // Okay, abstract class is decoratable
abstract class GitHubService {
@GET("users/{user}/repos") // ERROR: Cannot decorate an abstract class member
abstract Call<List<Repo>> listRepos(@Path("user") user: string); // ERROR
}
要解决这样的限制,我们不能使用抽象类,所以它变成了
@MyAPI() // Okay, abstract class is decoratable
class GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") user: user) {
throw new Error('unimplemented');
}
}
这显然不是优雅的做法。
我认为这样的功能可以在不破坏现有有效代码的情况下实现。
装饰器函数可以通过检查属性描述符的值是否为 undefined 来判断它是否正在装饰一个抽象成员。
function ClassMemberDecorator(prototype: {}, name: string, pd: PropertyDescriptor) {
if (typeof pd.value === 'undefined') { // we're decorating abstract member
}
}
function ClassMemberParamDecorator(prototype: {}, name: string, index: number) {
if (typeof prototype[name] === 'undefiend') { // we're decorating abstract member param
}
}
由于在目标 ES3 时,PropertyDescriptor.value
总是未定义的,因此这个特性仅在目标 ES5 及以上时才受支持。
检查清单
我的建议满足以下准则:
- 这不会对现有的 TypeScript/JavaScript 代码造成破坏性更改
- 这不会改变现有 JavaScript 代码的运行时行为
- 这可以在不根据表达式的类型生成不同的 JS 的情况下实现
- 这不是一个运行时特性(例如库功能、JavaScript 输出的非 ECMAScript 语法等)
- 这个特性将与 TypeScript's Design Goals 的其他部分保持一致。
9条答案
按热度按时间i5desfxk1#
+1,非常希望拥有它。我的用例是为electron应用程序中的类生成IPC代理。
xbp102n02#
我很想看到这个实现。
不仅仅是抽象类,接口也可以。它对于TypeScript编译器来说是一个方便的提示——自定义转换器。在处理接口时,无需将任何内容输出到最终的JavaScript代码中。
我在TypeScript runtime reflection上工作,它可以生成大量有用的数据,这些数据可以在运行时读取到元数据库中。你可以查找函数、接口、类及其构造函数、方法、参数、装饰器等。
如果能为接口添加注解,那将会非常有用。例如,我可以找到它们,找到它们的实现,并将指定在接口上的内容应用到实现中。
rsl1atfo3#
抽象类成员函数的装饰能力与接口不同:接口不在值空间中,编译后会被擦除。相反,抽象类在JS中只是转换为一个类,甚至可以示例化它。
到目前为止,TypeScript不允许这样做,所以我使用了这样的丑陋代码:
然后,我向您展示如何生成JS代码(从TypeScript playground复制/粘贴):
我插入了如果在
Test
类上设置抽象方法nonExistingMethod()
时将生成的代码。我还运行了这段代码,有和没有Reflect.decorate
(因为它的存在性在生成的代码中被检查)并且一切都很好。使用那个抽象类和现代JavaScript(通常是使用Proxy进行拦截),在抽象成员上进行装饰是有意义的。请在编译器中删除对抽象方法上的错误:
A decorator can only decorate a method implementation, not an overload.ts(1249)
。6pp0gazn4#
你好,正如我在之前的评论中所提到的,似乎应该允许装饰抽象类的抽象成员函数?还缺少什么样的反馈?
v6ylcynt5#
@ppoulard,我们现在并不想改变装饰器语义(尤其是以一种允许之前不允许的事情的方式),因为有提案正在TC39委员会中通过以标准化它们。
v7pvogib6#
真的希望看到错误被移除。现在正在使用装饰器来创建一个使用抽象类的模式,并提供伪代码。
qeeaahzv7#
这个特性是否可以在ECMA装饰器中使用?@RyanCavanaugh
ckocjqey8#
看起来现在无法在抽象类成员上使用它,那么当前的实现应该是这样的:
代码可以在TS Playground上找到
功能等待室>w<
iecba09b9#
这将是非常棒的!
但到目前为止,唯一的方法(不是最佳方法,因为它忽略了整个代码块中的错误)是拥有
// @ts-expect-error
或// @ts-ignore
:如果可能的话,在
// @ts-expect-error
或// @ts-ignore
处指定某些错误代码以跳过这些方法将是近乎完美的临时解决方案。问题:#38409,#19139等。也许类似于// @ts-expect-error("ts(1249)")
。