Typescript 中私有方法的类型安全装饰器
Type-safe decorator for private method in Typescript
我试图在打字稿中实现一个只能应用于异步函数的装饰器。
如果装饰器应用于 none 异步函数,编译应该会引发错误。
这是我到目前为止尝试过的方法:
type AsyncFunction = (...args: any[]) => Promise<any>
function MyDecorator(/* params as needed */) {
return function <P extends string>(target: Record<P, AsyncFunction> , propertyKey: P) {
console.log("Implementation of MyDecorator")
}
}
class SomeClassWithPrivateMethod {
@MyDecorator()
private async somePrivateMethod() {
}
@MyDecorator()
async somePublicMethod() {
}
}
问题是,它不适用于私有方法并出现以下错误消息:
Argument of type 'SomeClassWithPrivateMethod' is not assignable to parameter of type 'Record<"somePrivateMethod", AsyncFunction>'.
Property 'somePrivateMethod' is private in type 'SomeClassWithPrivateMethod' but not in type 'Record<"somePrivateMethod", AsyncFunction>'.
我必须更改什么才能使其适用于私有方法?
TypeScript 不支持类型声明中的 'private'|'public'|'static'
修饰符。
您可以在class
中声明static
修饰符作为索引类型。参见 docs
Private
类型的处理方式与其他类型不同。您可以将其视为某种名义类型。
考虑这个例子:
type AsyncFunction = (...args: any[]) => Promise<any>
abstract class Base {
private async somePrivateMethod() { }
}
function MyDecorator() {
return function <P extends string>(target: Base, descriptor: PropertyDescriptor) {
console.log("Implementation of MyDecorator")
}
}
class SomeClassWithPrivateMethod {
@MyDecorator()
private async somePrivateMethod() {}
@MyDecorator()
async somePublicMethod() { }
}
尽管 TS 具有结构类型系统,但您会收到此错误:
Argument of type 'SomeClassWithPrivateMethod' is not assignable to parameter of type 'Base'.
Types have separate declarations of a private property 'somePrivateMethod'.(2345)
因此,Base
的私有方法不等于SomeClassWithPrivateMethod
的private
方法
如果你从它们两个中删除 private
标志 - 它会编译。
因为不可能创建一个 type/class/interface 来表示 SomeClassWithPrivateMethod
的私有类型,所以您不能将此装饰器应用于私有方法或多或少是安全的,更重要的是 通用方式。
但是有一个解决方法。
您可以使用 SomeClassWithPrivateMethod
class 类型作为 target
参数。它会起作用
type AsyncFunction = (...args: any[]) => Promise<any>
abstract class Base {
async somePrivateMethod() { }
}
function MyDecorator() {
return function <P extends string>(target: SomeClassWithPrivateMethod, prop: P, descriptor: PropertyDescriptor) {
console.log("Implementation of MyDecorator")
}
}
class SomeClassWithPrivateMethod {
@MyDecorator()
private async somePrivateMethod() { }
@MyDecorator()
async somePublicMethod() { }
}
或使用 target:unknown
.
function MyDecorator() {
return function <P extends string>(target: unknown, prop: P, descriptor: PropertyDescriptor) {
console.log("Implementation of MyDecorator")
}
}
对于我的用例,我找到了一个非常简单的解决方案
- 使用打字稿 4.6.3 测试 -
可以将描述符参数限制为特定类型,而不是对目标参数应用约束:
type AsyncFunction = (...args: any[]) => Promise<any>
function MyDecorator(/* params as needed */) {
return function(target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<AsyncFunction>) {
console.log("Implementation of MyDecorator")
}
}
TypedPropertyDescriptor<AsyncFunction>
是这里的关键。 TypedPropertyDescriptor
是来自打字稿的内置类型。
我试图在打字稿中实现一个只能应用于异步函数的装饰器。 如果装饰器应用于 none 异步函数,编译应该会引发错误。
这是我到目前为止尝试过的方法:
type AsyncFunction = (...args: any[]) => Promise<any>
function MyDecorator(/* params as needed */) {
return function <P extends string>(target: Record<P, AsyncFunction> , propertyKey: P) {
console.log("Implementation of MyDecorator")
}
}
class SomeClassWithPrivateMethod {
@MyDecorator()
private async somePrivateMethod() {
}
@MyDecorator()
async somePublicMethod() {
}
}
问题是,它不适用于私有方法并出现以下错误消息:
Argument of type 'SomeClassWithPrivateMethod' is not assignable to parameter of type 'Record<"somePrivateMethod", AsyncFunction>'.
Property 'somePrivateMethod' is private in type 'SomeClassWithPrivateMethod' but not in type 'Record<"somePrivateMethod", AsyncFunction>'.
我必须更改什么才能使其适用于私有方法?
TypeScript 不支持类型声明中的 'private'|'public'|'static'
修饰符。
您可以在class
中声明static
修饰符作为索引类型。参见 docs
Private
类型的处理方式与其他类型不同。您可以将其视为某种名义类型。
考虑这个例子:
type AsyncFunction = (...args: any[]) => Promise<any>
abstract class Base {
private async somePrivateMethod() { }
}
function MyDecorator() {
return function <P extends string>(target: Base, descriptor: PropertyDescriptor) {
console.log("Implementation of MyDecorator")
}
}
class SomeClassWithPrivateMethod {
@MyDecorator()
private async somePrivateMethod() {}
@MyDecorator()
async somePublicMethod() { }
}
尽管 TS 具有结构类型系统,但您会收到此错误:
Argument of type 'SomeClassWithPrivateMethod' is not assignable to parameter of type 'Base'.
Types have separate declarations of a private property 'somePrivateMethod'.(2345)
因此,Base
的私有方法不等于SomeClassWithPrivateMethod
private
方法
如果你从它们两个中删除 private
标志 - 它会编译。
因为不可能创建一个 type/class/interface 来表示 SomeClassWithPrivateMethod
的私有类型,所以您不能将此装饰器应用于私有方法或多或少是安全的,更重要的是 通用方式。
但是有一个解决方法。
您可以使用 SomeClassWithPrivateMethod
class 类型作为 target
参数。它会起作用
type AsyncFunction = (...args: any[]) => Promise<any>
abstract class Base {
async somePrivateMethod() { }
}
function MyDecorator() {
return function <P extends string>(target: SomeClassWithPrivateMethod, prop: P, descriptor: PropertyDescriptor) {
console.log("Implementation of MyDecorator")
}
}
class SomeClassWithPrivateMethod {
@MyDecorator()
private async somePrivateMethod() { }
@MyDecorator()
async somePublicMethod() { }
}
或使用 target:unknown
.
function MyDecorator() {
return function <P extends string>(target: unknown, prop: P, descriptor: PropertyDescriptor) {
console.log("Implementation of MyDecorator")
}
}
对于我的用例,我找到了一个非常简单的解决方案
- 使用打字稿 4.6.3 测试 -
可以将描述符参数限制为特定类型,而不是对目标参数应用约束:
type AsyncFunction = (...args: any[]) => Promise<any>
function MyDecorator(/* params as needed */) {
return function(target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<AsyncFunction>) {
console.log("Implementation of MyDecorator")
}
}
TypedPropertyDescriptor<AsyncFunction>
是这里的关键。 TypedPropertyDescriptor
是来自打字稿的内置类型。