TypeScript 箭头函数上的装饰器会产生意外的结果,

vhmi4jdf  于 6个月前  发布在  TypeScript
关注(0)|答案(4)|浏览(112)

Bug报告

🔎搜索关键词

装饰器、箭头函数、异步生成器

💻代码

这段代码按预期工作

export default class Que {
	private static async * makeStream(): AsyncGenerator<unknown, any, any> {
		let r = yield
		while (1) r = yield await r()
	}

	q = Que.makeStream()

	constructor() {
		this.q.next()
	}

	add = async <T>(fn: (...args: any[]) => Promise<T>) => (await this.q.next(fn)).value as T
}

export function qued(
	_: unknown,
	__: string,
	descriptor: PropertyDescriptor,
) {
	const que = new Que()
	const original = descriptor.value

	descriptor.value = async function (...args: any[]) {
		return que.add(() => original.call(this, ...args)) as Promise<ReturnType<typeof original>>
	}
}

class Tested {
	count: number[] = []

	@qued
	async testMethod(v: number) {
		return new Promise<number>(resolve => {
			setTimeout(() => {
				this.count.push(v)
				resolve(v)
			}, 20 - v * 2)
		})
	}
}

async function test(){
	const testedInstance = new Tested()

	for (const val of [1,2,3,4,5]) {
		testedInstance.testMethod(val)
	}

	await testedInstance.testMethod(6)

	console.log(testedInstance.count)
}

test()
 // [1,2,3,4,5,6]

这段代码不起作用

export default class Que {
	private static async * makeStream(): AsyncGenerator<unknown, any, any> {
		let r = yield
		while (1) r = yield await r()
	}

	q = Que.makeStream()

	constructor() {
		this.q.next()
	}

	add = async <T>(fn: (...args: any[]) => Promise<T>) => (await this.q.next(fn)).value as T
}

export function qued(
	_: unknown,
	__: string,
	descriptor?: PropertyDescriptor, // <--
) {
	const que = new Que()
	const original = descriptor!.value

	descriptor!.value = async function (...args: any[]) {
		return que.add(() => original.call(this, ...args)) as Promise<ReturnType<typeof original>>
	}
}

class Tested {
	count: number[] = []

	@qued
	testMethod = async (v: number) => { // <-- turn into arrow function
		return new Promise<number>(resolve => {
			setTimeout(() => {
				this.count.push(v)
				resolve(v)
			}, 20 - v * 2)
		})
	}
}

async function test(){
	const testedInstance = new Tested()

	for (const val of [1,2,3,4,5]) {
		testedInstance.testMethod(val)
	}

	await testedInstance.testMethod(6)

	console.log(testedInstance.count)
}

test()
 // [6]

当方法是静态的或者不是箭头函数时,一切都按预期工作。然而,当方法被写成箭头函数时,会发生这种情况。我是不是漏掉了什么?
Que.add()在没有装饰器的情况下按预期工作。

mklgxw1f

mklgxw1f1#

也许你可以提供一个Playground链接,就像问题模板要求的那样?你提供的代码不起作用。

myss37ts

myss37ts2#

也许你可以提供一个Playground链接,就像问题模板要求的那样?你提供的代码不起作用。
TypeScriptPlayground在运行TypeScript时存在太多问题,所以我无法运行。
我已经编辑了原始帖子,包括两个我可以编译和运行的示例,如果第一个有问题的话,我很抱歉!
编辑:看起来,当你使用箭头函数时,它不会在装饰器中初始化,但在装饰器返回后,属性会被初始化并用原始函数覆盖。无论如何,我们需要一种方法来装饰箭头函数以及普通属性。

avkwfej4

avkwfej43#

TypeScript Playground在运行TypeScript时存在太多问题,所以我无法使用。例如?

bkhjykvo

bkhjykvo4#

我尝试了一下 - 如果你使用的是较旧的目标,你会得到 lib 错误。此外,playground使用JSX,这与通用箭头函数语法相冲突。有点痛苦,但你可以通过将JSX设置为 none 并使用 /// <reference lib="esnext" /> 来消除这些错误。
尽管如此,你至少能提供一些类似于 tsconfig 的选项吗?

相关问题