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],
});
});
打破
}
回报承诺;
}
}
是否有更好的惯例来实现我想要实现的目标?我写函数重载主要是为了得到我现在从你那里学到的不存在的关系。在函数开始时使用类型保护是否是一个好主意?如果你知道一些最佳实践,我很想学习