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

Typescript 无法使方法重载与歧视性联合一起工作。怎么了?,typescript,Typescript,如果没有as IUpdateRequestPromiseProxy断言,如何使以下代码正常工作 import { Id } from 'app/core/persistence'; import { IPersistence } from '..'; import { IBaseEntity } from '../../..'; /* * Missing changeFn indicates delete */ type IChangeRequestPromiseProxy<TEnt

如果没有
as IUpdateRequestPromiseProxy
断言,如何使以下代码正常工作

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;
    }
}
从'app/core/persistence'导入{Id};
从“..”导入{IPersistence};
从'../../..'导入{IBaseEntity};
/*
*缺少更改fn表示删除
*/
类型IChangeRequestPromiseProxy=
|IUPDateRequestPromisePromisePromiseProxy
|委托书;
接口IUpdateRequestPromiseProxy{
id:id;
种类:“更新”;
解析(值:IPersistence):无效;
拒绝(原因:任何):无效;
变更fn(实体:IPersistence):IPersistence;
}
接口IDeleteRequestPromiseProxy{
id:id;
种类:'删除';
解析(值:void):void;
拒绝(原因:任何):无效;
}
导出类队列服务{
私有changeRequestsQueue:Array=[];
私有flushingQueueMutex:boolean=false;
公共异步排队(id:id,种类:'delete'):承诺;
公共异步排队(
id:id,
种类:'更新',
变更fn:(实体:IPersistence)=>IPersistence,
):承诺;
公共异步排队(
id:id,
种类:“删除”|“更新”,
变更fn?:(实体:IPersistence)=>IPersistence,
):承诺{
让承诺:承诺;
开关(种类){
案例“删除”:
承诺=新承诺(异步(解析、拒绝)=>{
这是.changeRequestsQueue.push({
身份证件
友善的
决定
拒绝
});
});
打破
案例“更新”:
违约:
承诺=新承诺(异步(解析、拒绝)=>{
这是.changeRequestsQueue.push({
身份证件
友善的
决定
拒绝
改变fn,
}作为IUPDaterRequestPromisePromisePromise);
});
打破
}
回报承诺;
}
}
如果删除断言,则会出现错误:

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)
类型为“{id:string;kind:“update”;resolve:(value?:IPersistence | PromiseLike | undefined)=>void;reject:(reason?:any)=>void;changeFn:((entity:IPersistence)=>IPersistence)| undefined;}”的参数不能分配给类型为“IChangeRequestPromisePromiseProxy”的参数。
类型“{id:string;kind:“update”;resolve:(value?:IPersistence | PromiseLike | undefined)=>void;拒绝:(reason?:any)=>void;changeFn:((entity:IPersistence)=>IPersistence)| undefined;}”不能分配给类型“IUpdateRequestPromisePromiseProxy”。
属性“changeFn”的类型不兼容。
类型“((实体:IPersistence)=>IPersistence)|未定义”不可分配给类型“(实体:IPersistence)=>IPersistence”。
类型“未定义”不可分配给类型“(实体:IPersistence)=>IPersistence'.ts(2345)

问题在于typescript没有跟踪由重载创建的
kind
changeFn
之间的关系。因此,就ts而言,
changeFn
可能仍然是未定义的,即使您在
kind==“update”
分支上

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

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;
    }
}
导出类队列服务{
私有changeRequestsQueue:Array=[];
私有flushingQueueMutex:boolean=false;
公共异步排队(id:id,种类:'delete'):承诺;
公共异步排队(
id:id,
种类:'更新',
变更fn:(实体:IPersistence)=>IPersistence,
):承诺;
公共异步排队(
id:id,
…r:['delete']|['update',(实体:IPersistence)=>IPersistence],
):承诺{
让承诺:承诺;
开关(r[0]){
案例“删除”:
承诺=新承诺(异步(解析、拒绝)=>{
这是.changeRequestsQueue.push({
身份证件
种类:r[0],
决定
拒绝
});
});
打破
案例“更新”:
违约:
承诺=新承诺(异步(解析、拒绝)=>{
这是.changeRequestsQueue.push({
身份证件
种类:r[0],
决定
拒绝
更改fn:r[1],
});
});
打破
}
回报承诺;
}
}

是否有更好的惯例来实现我想要实现的目标?我写函数重载主要是为了得到我现在从你那里学到的不存在的关系。在函数开始时使用类型保护是否是一个好主意?如果你知道一些最佳实践,我很想学习