如何在TypeScript中键入此符号迭代器实现

rjee0c15  于 2022-12-30  发布在  TypeScript
关注(0)|答案(1)|浏览(135)

我正在试着让这个工作的JavaScript(但不是我的:P)通过类型检查。也许这只是在一天晚了,但我可以使用一些帮助。

class GPUTexture {}

class BaseState<T> {
    webgpuObject: T | null;

    constructor() {
        this.webgpuObject = null;
    }
}

class TextureState extends BaseState<GPUTexture> {}

interface CaptureStateBase<GPUType> {
    webgpuObject: GPUType | null;
}

class ObjectRegistry<GPUType extends Object, CaptureState extends CaptureStateBase<GPUType>> {
    iterating: boolean;
    dataMap: WeakMap<GPUType, CaptureState>;
    objects: WeakRef<GPUType>[];

    constructor() {
        this.dataMap = new WeakMap();
        this.objects = [];
        this.iterating = false;
    }

    add(obj: GPUType, data: CaptureState) {
        if (this.iterating) {
            throw new Error('Mutating Registry while iterating it.');
        }

        this.dataMap.set(obj, data);
        this.objects.push(new WeakRef(obj));
        data.webgpuObject = obj;
    }

    get(obj: GPUType) {
        return this.dataMap.get(obj);
    }

    [Symbol.iterator](): IterableIterator<CaptureState> {
        let i = 0;
        this.iterating = true;

        return {
            registry: this,
            next() {
                while (i < this.registry.objects.length) {
                    const obj = this.registry.objects[i++].deref();
                    if (obj === undefined) {
                        continue;
                    }
                    return { value: this.registry.get(obj), done: false };
                }
                this.registry.iterating = false;
                return { done: true };
            },
        };
    }
}

const textures = new ObjectRegistry<GPUTexture, TextureState>();

我尝试简化代码,但我不确定我是否理解错误。我实际上看到了两个错误。一个是,typescript似乎混淆了next中的this。我抱怨this.registry不存在
另一个是
(方法)迭代器〈捕获状态,任意,未定义〉. next(...参数:[]| [未定义]):迭代器结果〈捕获状态,任意〉
类型'()=〉{值:任何;完成:错误;}| {完成:真;值?:未定义; "}"不能赋给类型"(...参数:[]| [未定义])=〉迭代器结果〈捕获状态,任意〉'。
类型"{值:任何;完成:错误;}| {完成:真;值?:未定义; }"不能赋给类型" IteratorResult〈CaptureState,any〉"。
键入"{完成:真;值?:无法将"未定义;}"赋给类型"IteratorResult〈CaptureState,any〉"。
键入"{完成:真;值?:未定义;"}"不能赋给类型" IteratorReturnResult "。
属性"value"在类型"{done:真;值?:未定义;}",但在类型" IteratorReturnResult "中是必需的。(2322)
打字场
我试图通过像这样向上移动next来修复第一个问题

class GPUTexture {}

class BaseState<T> {
    webgpuObject: T | null;

    constructor() {
        this.webgpuObject = null;
    }
}

class TextureState extends BaseState<GPUTexture> {}

interface CaptureStateBase<GPUType> {
    webgpuObject: GPUType | null;
}

class ObjectRegistry<GPUType extends Object, CaptureState extends CaptureStateBase<GPUType>> {
    iterating: boolean;
    dataMap: WeakMap<GPUType, CaptureState>;
    objects: WeakRef<GPUType>[];

    constructor() {
        this.dataMap = new WeakMap();
        this.objects = [];
        this.iterating = false;
    }

    add(obj: GPUType, data: CaptureState) {
        if (this.iterating) {
            throw new Error('Mutating Registry while iterating it.');
        }

        this.dataMap.set(obj, data);
        this.objects.push(new WeakRef(obj));
        data.webgpuObject = obj;
    }

    get(obj: GPUType) {
        return this.dataMap.get(obj);
    }

    [Symbol.iterator](): IterableIterator<CaptureState> {
        let i = 0;
        this.iterating = true;

        const next = () => {
            while (i < this.objects.length) {
                const obj = this.objects[i++].deref();
                if (obj === undefined) {
                    continue;
                }
                return { value: this.get(obj), done: false };
            }
            this.iterating = false;
            return { done: true };
        };

        return { next };
    }
}

const textures = new ObjectRegistry<GPUTexture, TextureState>();

打字场
这解决了第一个错误,但没有解决第二个错误

q3qa4bjr

q3qa4bjr1#

在迭代器对象上引用一个单独的this.registry作为自定义值是很奇怪的,可能会导致问题。完全抛弃它,只使用一个arrow函数和外部的this会更容易。这样,它的类型就可以 * 正常工作 *-你的arrow函数是正确的想法。

next: () => {
    while (i < this.objects.length) {
        const obj = this.objects[i++].deref();
        // ...

在此之后,typing here只会再发出一个警告:

[Symbol.iterator](): IterableIterator<CaptureState> {

这可以通过指定this与示例化的类相同并让TypeScript自己推断迭代器类型来修复。

[Symbol.iterator](this: ObjectRegistry<GPUType, CaptureState>) {

Playground链接

属性"value"在类型"{done:真;值?:未定义;}",但在类型" IteratorReturnResult "中是必需的。(2322)
可以通过改变

return { done: true };

return { done: true, value: undefined };

但看起来没必要。

相关问题