无法使方法重载与歧视联合一起工作。怎么了?

2024-01-01

我怎样才能让下面的代码在没有as IUpdateRequestPromiseProxy<TEntity>断言?

import { Id } from 'app/core/persistence';
import { IPersistence } from '..';
import { IBaseEntity } from '../../..';

/*
 * Missing changeFn indicates delete
 */
type IChangeRequestPromiseProxy<TEntity extends IBaseEntity> =
    | IUpdateRequestPromiseProxy<TEntity>
    | IDeleteRequestPromiseProxy;

interface IUpdateRequestPromiseProxy<TEntity extends IBaseEntity> {
    id: Id;
    kind: 'update';
    resolve(value: IPersistence<TEntity>): void;
    reject(reason: any): void;
    changeFn(entity: IPersistence<TEntity>): IPersistence<TEntity>;
}

interface IDeleteRequestPromiseProxy {
    id: Id;
    kind: 'delete';
    resolve(value: void): void;
    reject(reason: any): void;
}

export class QueueService<TEntity extends IBaseEntity> {
    private changeRequestsQueue: Array<IChangeRequestPromiseProxy<TEntity>> = [];
    private flushingQueueMutex: boolean = false;

    public async enqueue(id: Id, kind: 'delete'): Promise<void>;
    public async enqueue(
        id: Id,
        kind: 'update',
        changeFn: (entity: IPersistence<TEntity>) => IPersistence<TEntity>,
    ): Promise<IPersistence<TEntity>>;
    public async enqueue(
        id: Id,
        kind: 'delete' | 'update',
        changeFn?: (entity: IPersistence<TEntity>) => IPersistence<TEntity>,
    ): Promise<IPersistence<TEntity> | void> {
        let promise: Promise<IPersistence<TEntity> | void>;
        switch (kind) {
            case 'delete':
                promise = new Promise<void>(async (resolve, reject) => {
                    this.changeRequestsQueue.push({
                        id,
                        kind,
                        resolve,
                        reject,
                    });
                });
                break;
            case 'update':
            default:
                promise = new Promise<IPersistence<TEntity>>(async (resolve, reject) => {
                    this.changeRequestsQueue.push({
                        id,
                        kind,
                        resolve,
                        reject,
                        changeFn,
                    } as IUpdateRequestPromiseProxy<TEntity>);
                });
                break;
        }

        return promise;
    }
}

如果我删除断言,我会收到错误:

Argument of type '{ id: string; kind: "update"; resolve: (value?: IPersistence<TEntity> | PromiseLike<IPersistence<TEntity>> | undefined) => void; reject: (reason?: any) => void; changeFn: ((entity: IPersistence<TEntity>) => IPersistence<...>) | undefined; }' is not assignable to parameter of type 'IChangeRequestPromiseProxy<TEntity>'.
  Type '{ id: string; kind: "update"; resolve: (value?: IPersistence<TEntity> | PromiseLike<IPersistence<TEntity>> | undefined) => void; reject: (reason?: any) => void; changeFn: ((entity: IPersistence<TEntity>) => IPersistence<...>) | undefined; }' is not assignable to type 'IUpdateRequestPromiseProxy<TEntity>'.
    Types of property 'changeFn' are incompatible.
      Type '((entity: IPersistence<TEntity>) => IPersistence<TEntity>) | undefined' is not assignable to type '(entity: IPersistence<TEntity>) => IPersistence<TEntity>'.
        Type 'undefined' is not assignable to type '(entity: IPersistence<TEntity>) => IPersistence<TEntity>'.ts(2345)

问题是打字稿不跟踪之间的关系kind and changeFn这是由重载创建的。所以changeFn就 ts 而言,即使您位于kind === 'update' branch.

最简单的解决方案是使用非空断言:

this.changeRequestsQueue.push({
    id,
    kind: 'update',
    resolve,
    reject,
    changeFn: changeFn!,
});

如果您想要完整的非断言版本,可以在参数中使用可区分的元组来完成,尽管我不确定它是否值得额外的复杂性:

export class QueueService<TEntity extends IBaseEntity> {
    private changeRequestsQueue: Array<IChangeRequestPromiseProxy<TEntity>> = [];
    private flushingQueueMutex: boolean = false;

    public async enqueue(id: Id, kind: 'delete'): Promise<void>;
    public async enqueue(
        id: Id,
        kind: 'update',
        changeFn: (entity: IPersistence<TEntity>) => IPersistence<TEntity>,
    ): Promise<IPersistence<TEntity>>;
    public async enqueue(
        id: Id,
        ...r: ['delete'] | ['update', (entity: IPersistence<TEntity>) => IPersistence<TEntity>],
    ): Promise<IPersistence<TEntity> | void> {
        let promise: Promise<IPersistence<TEntity> | void>;
        switch (r[0]) {
            case 'delete':
                promise = new Promise<void>(async (resolve, reject) => {
                    this.changeRequestsQueue.push({
                        id,
                        kind: r[0],
                        resolve,
                        reject,
                    });
                });
                break;
            case 'update':
            default:
                promise = new Promise<IPersistence<TEntity>>(async (resolve, reject) => {
                    this.changeRequestsQueue.push({
                        id,
                        kind: r[0],
                        resolve,
                        reject,
                        changeFn: r[1],
                    });
                });
                break;
        }

        return promise;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法使方法重载与歧视联合一起工作。怎么了? 的相关文章

随机推荐