TypeScript:基于 class 类型参数的函数重载

TypeScript: Function overload based on class type of parameter

是否可以根据参数的 class 类型应用 TypeScript 函数的重载?

我意识到 "classes" 将在输出中被编译为普通函数,但我希望根据输入类型进行类型检查。

目标是为服务器通信创建 send() 函数,return 是基于请求类型的类型化响应。但是,无论传入的 class 类型如何,TypeScript 似乎总是选择第一个重载。

interface IRequest {
  getBody(): object;
}

class UserRequest implements IRequest {
  getBody() {
    return { type: 'user', id: 7 };
  }
}

class CompanyRequest implements IRequest {
  getBody() {
    return { type: 'company', id: 42 };
  }
}

interface IUserResponse {
  userName: string;
}

interface ICompanyResponse {
  companyName: string;
}

function send(request: UserRequest): Promise<IUserResponse>;
function send(request: CompanyRequest): Promise<ICompanyResponse>;
async function send(request: IRequest): Promise<any> {
  const response = await fetch('https://example.com/service', {
    body: request.getBody(),
  });
  return response.json();
}

async function test() {

  // Works
  const userResponse = await send(new UserRequest());
  userResponse.userName;

  // Error: [ts] Property 'companyName' does not exist on type 'IUserResponse'. [2339]
  const companyResponse = await send(new CompanyRequest());
  companyResponse.companyName;

}

交换声明的重载的顺序可以逆转问题(return 类型将始终是 CompanyRequest 而不是 UserRequest)。

你的问题似乎是编译器认为 UserRequestCompanyRequest 在结构上是兼容的,这意味着它们本质上是相同的类型。所以第一个重载总是被选择,坏事发生了。避免这种情况的最简单方法是为至少一种类型添加属性,以便编译器 recognizes they are distinct types。这是一种可能的方法:

class UserRequest implements IRequest {
  getBody() {
    return { type: 'user', id: 7 };
  }
  readonly className = "UserRequest"
}

class CompanyRequest implements IRequest {
  getBody() {
    return { type: 'company', id: 42 };
  }
  readonly className = "CompanyRequest"
}

在那种情况下,readonly 属性 className 得到一些不同的文字字符串值。希望有所帮助。祝你好运!