Typescript:重载并检查泛型类型
我有这个界面:Typescript:重载并检查泛型类型,typescript,Typescript,我有这个界面: export interface ICRUDService<T extends IModel> { save(item: T): Promise<void>; save(items: T[]): Promise<void>; save(item: IRemoteData<T>): Promise<void>; save(items: IRemoteData<T>[]): Pr
export interface ICRUDService<T extends IModel> {
save(item: T): Promise<void>;
save(items: T[]): Promise<void>;
save(item: IRemoteData<T>): Promise<void>;
save(items: IRemoteData<T>[]): Promise<void>;
save(item: Partial<T>): Promise<void>;
}
导出接口ICRUDService{
保存(项目:T):承诺;
保存(项目:T[]):承诺;
保存(项目:IRemoteData):承诺;
保存(项目:IRemoteData[]):承诺;
保存(项目:部分):承诺;
}
以及一项实施:
export abstract class AbstractCRUDServiceImpl<T extends IModel> implements ICRUDService<T> {
async save(item: T): Promise<void>;
async save(items: T[]): Promise<void>;
async save(item: IRemoteData<T>): Promise<void>;
async save(items: IRemoteData<T>[]): Promise<void>;
async save(item: Partial<T>): Promise<void>;
async save(item: any): Promise<void> {
if (typeof item === T)
// ...
}
}
导出抽象类AbstractCRUDServiceImpl实现ICRUDService{
异步保存(项目:T):承诺;
异步保存(项:T[]):承诺;
异步保存(项目:IRemoteData):承诺;
异步保存(项:IRemoteData[]):承诺;
异步保存(项目:部分):承诺;
异步保存(项目:任意):承诺{
如果(项目类型===T)
// ...
}
}
但它说:
“T”仅指类型,但用作值
这里是ts(2693)'
解决这个问题的正确方法是什么?请记住,当代码实际运行时,所有键入信息都将消失。因此,您不能依赖类型来确定运行时对象是什么 相反,您必须确定值是否具有与所需类型相同的功能 其次,实现函数的参数应该是一个类型,它是覆盖中每种类型的并集
假设您的
IModel
和IRemoteData
设置如下:
interface IRemoteData<T> {
remoteData: T
}
interface IModel {
id: number
}
export abstract class AbstractCRUDServiceImpl<T extends IModel> implements ICRUDService<T> {
async save(item: T): Promise<void>;
async save(items: T[]): Promise<void>;
async save(item: IRemoteData<T>): Promise<void>;
async save(items: IRemoteData<T>[]): Promise<void>;
async save(item: Partial<T>): Promise<void>;
async save(items: IRemoteData<T> | T): Promise<void>; // Added this override
async save(item: T | T[] | IRemoteData<T> | IRemoteData<T>[] | Partial<T>): Promise<void> {
if (Array.isArray(item)) {
// item is array in this scope, iterate over each item and save them
for (const singleItem of item) {
await this.save(singleItem)
}
} else {
// item is not an array in this scope
if ('id' in item) {
item // T | Partial<T>
} else {
item // IRemoteData<T>
}
}
}
}
这是条件的数组处理分支所必需的。问题是,当你知道它是数组之后,你就不知道它是什么数组了。因此,在迭代项目时,每个项目的类型为:
T | IRemoteData<T>
此重载将某些参数类型绑定到某些返回类型。但是你的函数不需要这样,可以用一个函数来表示,它的参数是很多东西的简单结合
所有这一切都意味着这应该是可行的:
export abstract class AbstractCRUDServiceImpl<T extends IModel> {
async save(item: T | T[] | IRemoteData<T> | IRemoteData<T>[] | Partial<T>): Promise<void> {
if (Array.isArray(item)) {
// item is array in this scope, iterate over each item and save them
for (const singleItem of item) {
await this.save(singleItem)
}
} else {
// item is not an array in this scope
if ('id' in item) {
item // T | Partial<T>
} else {
item // IRemoteData<T>
}
}
}
}
导出抽象类AbstractCRUDServiceImpl{
异步保存(项目:T | T[]| IRemoteData | IRemoteData[]|部分):承诺{
if(阵列isArray(项目)){
//项是此范围中的数组,遍历每个项并保存它们
用于(项目的常量单个项目){
等待此操作。保存(singleItem)
}
}否则{
//项不是此作用域中的数组
如果(项目中的“id”){
项目//T |部分
}否则{
项目//IRemoteData
}
}
}
}
什么是
IModel
和IRemoteData
?另外,您确定要在此处进行覆盖吗?由于返回类型没有改变,您只需要将一个方法定义为save(item:t | t[]| IRemoteData | IRemoteData[]| Partial):Promise
IModel是一个基本类型,它只有一个“id”字段。IRemoteData是带有一些额外字段的T的包装器。当然,我只能定义一个方法,但这不是方法重写的重点吗?同时为intellisense提供选项。@AlexWayne,即使我将它们合并到一个方法中,我仍然会遇到同样的问题。。?
async save(items: IRemoteData<T> | T): Promise<void>; // Added this override
function foo(a: number): string
function foo(a: string): number
function foo(a: number|string): number|string {
if (typeof a === 'string') {
return 123
} else {
return 'a string'
}
}
export abstract class AbstractCRUDServiceImpl<T extends IModel> {
async save(item: T | T[] | IRemoteData<T> | IRemoteData<T>[] | Partial<T>): Promise<void> {
if (Array.isArray(item)) {
// item is array in this scope, iterate over each item and save them
for (const singleItem of item) {
await this.save(singleItem)
}
} else {
// item is not an array in this scope
if ('id' in item) {
item // T | Partial<T>
} else {
item // IRemoteData<T>
}
}
}
}