是否可以根据参数的类类型来应用TypeScript函数的重载?
我意识到“类”将在输出中被编译为普通函数,但我希望根据输入类型来进行类型检查。
目标是为服务器通信创建一个send()
函数,该函数根据请求的类型返回类型化的响应。但是,无论传入的类类型如何,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;
}
交换声明的重载的顺序可解决此问题(返回类型始终为CompanyRequest
而不是UserRequest
)。
答案 0 :(得分:2)
您的问题似乎是编译器认为UserRequest
和CompanyRequest
在结构上是兼容的,这意味着它们本质上是相同的类型。因此,总是选择第一个过载,并且会发生坏事。避免这种情况的最简单方法是向至少一种类型添加属性,以便编译器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
会获得一些不同的文字字符串值。希望能有所帮助。祝你好运!
答案 1 :(得分:1)
一般方法呢?
async function send<T>(request: T): Promise<T> {
const response = await fetch('https://example.com/service', {
body: request.getBody(),
});
return response.json();
}