You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript中为Symbol Iterator实现添加正确类型

解决TypeScript迭代器类型检查错误

我正尝试让一段别人写的可用JavaScript代码通过TypeScript类型检查,遇到了两个问题,以下是详细情况:

原始代码

class GPUTexture {}

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

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

class TextureState extends BaseState<GPUTexture> {
   name = "foo";
}

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>();
for (const tex of textures) {
  console.log(tex.name);
}

遇到的错误

  1. TypeScript对next方法内的this识别错误,提示this.registry不存在
  2. 迭代器返回值类型不匹配,具体错误信息:

(method) Iterator<CaptureState, any, undefined>.next(...args: [] | [undefined]): IteratorResult<CaptureState, any>
Type '() => { value: any; done: false; } | { done: true; value?: undefined; }' is not assignable to type '(...args: [] | [undefined]) => IteratorResult<CaptureState, any>'.
Type '{ value: any; done: false; } | { done: true; value?: undefined; }' is not assignable to type 'IteratorResult<CaptureState, any>'.
Type '{ done: true; value?: undefined; }' is not assignable to type 'IteratorResult<CaptureState, any>'.
Type '{ done: true; value?: undefined; }' is not assignable to type 'IteratorReturnResult'.
Property 'value' is optional in type '{ done: true; value?: undefined; }' but required in type 'IteratorReturnResult'.(2322)

尝试修改后的代码

我把next方法抽出来定义,解决了第一个错误,但第二个错误依然存在:

class GPUTexture {}

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

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

class TextureState extends BaseState<GPUTexture> {
    name = "foo";
}

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>();
for (const tex of textures) {
  console.log(tex.name);
}

内容的提问来源于stack exchange,提问作者user128511

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 22:25:19