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
)。
你的问题似乎是编译器认为 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
得到一些不同的文字字符串值。希望有所帮助。祝你好运!
是否可以根据参数的 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
)。
你的问题似乎是编译器认为 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
得到一些不同的文字字符串值。希望有所帮助。祝你好运!