TypeScript 中的函数重载与使用联合类型
Function Overloading in TypeScript vs Using a Union Type
我正在阅读有关函数重载的内容。本质上它们是,你正在创建比方说 3 个具有相同名称的函数,它们传递 3 个不同的参数和 return 类型。我是 TS 的新手,我想知道以下问题:传递联合类型和 returning 联合类型不会相同吗?还是完全不同的东西?
这就是我脑海中出现的例子。这行不行?
过载:
function f1(a: string) {
}
function f1(a: number) {
}
使用联合类型:
function f1(a: string | number):string | number {
}
函数重载将特定输入类型映射到特定 return 类型。使用联合,您只知道 return 是有效类型之一,但您失去了输入和输出之间的关联。这可能是问题,也可能不是问题,具体取决于您使用该功能的方式和位置。但这就是区别。
这是重载的样子。重载签名中的最后一行不是重载之一,它描述了实现的参数。有时你会看到 any
,但你也可以在这里使用并集。
function overloaded(a: string): string
function overloaded(a: number): number
function overloaded(a: any): any {
return a;
}
不同的参数 return 基于它们匹配的重载的特定类型。
const oNum: number = overloaded(0);
const oStr: string = overloaded("");
const oBool = overloaded(true); //error
在我们的联合中,两种输入类型都只是 return 联合,所以我们失去了特异性。
function union(a: string | number): string | number {
return a;
}
const uNum: string | number = union(0);
const uStr: string | number = union("");
const uBool = union(true); //error
还有第三个选项typescript generics。这使我们能够在接受无限多种类型的同时保持特异性。 boolean
示例现在可以使用了。我们告诉打字稿“查看参数的类型 a
并调用它 T
”。然后我们得到这个类型变量 T
,我们可以在 return 类型中使用它。在这里我们只是直接 returning 相同的类型 T
,但是你可以用它做很多事情。
function generic<T>(a: T): T {
return a;
}
const gNum: number = generic(0);
const gStr: string = generic("");
const gBool: boolean = generic(true);
只是扩展@Linda Paiste 关于泛型类型的评论
const gNum: number = generic(0);
这基本上就是在说
function generic<0>(a: 0): 0;
有时这可能不是您想要的。所以在使用泛型的时候,要传入一个类型参数:
const gNum: number = generic<number>(0);
对于函数参数类型,函数重载可以比联合类型和泛型类型更具体。
现实世界的例子:
createActivity
函数用于创建三种输入参数不同的活动。 CreateRenewalActivityParams
、CreateInsureActivityParams
和 CreateTrafficGenerationActivityParams
。
interface CreateActivityParams {
activityCode: string;
activityName: string;
activityDesc: string;
activityType: number;
activityTypeName: string;
startTime: string;
endTime: string;
paymentType: string | null;
}
interface CreateRenewalActivityParams extends CreateActivityParams {
installmentCases: any[];
}
interface CreateInsureActivityParams extends CreateActivityParams {
cases: any[];
}
interface CreateTrafficGenerationActivityParams extends CreateActivityParams {
cases: any[];
}
export async function createActivity(data: CreateTrafficGenerationActivityParams): Promise<boolean>;
export async function createActivity(data: CreateInsureActivityParams): Promise<boolean>;
export async function createActivity(data: CreateRenewalActivityParams): Promise<boolean>;
export async function createActivity(data: CreateActivityParams): Promise<boolean> {
return true;
}
// TSC throw error
createActivity({
activityCode: 'test code',
activityName: 'test name',
activityDesc: 'test desc',
activityType: 8,
activityTypeName: 'test type name',
startTime: '2021-07-20 00:00:00',
endTime: '2025-07-20 23:59:59',
paymentType: null,
cases: [
{
pictureCode: 'test pic code',
authDesc: null,
},
{
pictureCode: 'test pic code',
authDesc: null,
},
],
installmentCases: [],
});
export async function createActivityUnion(data: CreateTrafficGenerationActivityParams | CreateInsureActivityParams | CreateRenewalActivityParams) {
return true;
}
// TSC pass
createActivityUnion({
activityCode: 'test code',
activityName: 'test name',
activityDesc: 'test desc',
activityType: 8,
activityTypeName: 'test type name',
startTime: '2021-07-20 00:00:00',
endTime: '2025-07-20 23:59:59',
paymentType: null,
cases: [
{
pictureCode: 'test pic code',
authDesc: null,
},
{
pictureCode: 'test pic code',
authDesc: null,
},
],
installmentCases: [],
});
export async function createActivityGeneric<Data extends CreateActivityParams>(data: Data) {
return true;
}
// TSC pass
createActivityGeneric({
activityCode: 'test code',
activityName: 'test name',
activityDesc: 'test desc',
activityType: 8,
activityTypeName: 'test type name',
startTime: '2021-07-20 00:00:00',
endTime: '2025-07-20 23:59:59',
paymentType: null,
cases: [
{
pictureCode: 'test pic code',
authDesc: null,
},
{
pictureCode: 'test pic code',
authDesc: null,
},
],
installmentCases: [],
})
现在,我们希望函数的参数在同时包含installmentCases
和cases
字段时报类型不兼容错误,因为它们属于不同的activity类型,可以是使用函数重载完成。
我们可以为 createActivity
函数编写三个更具体的重载签名,其中包含上述三种参数类型和 CreateActivityParams
类型的通用实现签名。
我正在阅读有关函数重载的内容。本质上它们是,你正在创建比方说 3 个具有相同名称的函数,它们传递 3 个不同的参数和 return 类型。我是 TS 的新手,我想知道以下问题:传递联合类型和 returning 联合类型不会相同吗?还是完全不同的东西?
这就是我脑海中出现的例子。这行不行?
过载:
function f1(a: string) {
}
function f1(a: number) {
}
使用联合类型:
function f1(a: string | number):string | number {
}
函数重载将特定输入类型映射到特定 return 类型。使用联合,您只知道 return 是有效类型之一,但您失去了输入和输出之间的关联。这可能是问题,也可能不是问题,具体取决于您使用该功能的方式和位置。但这就是区别。
这是重载的样子。重载签名中的最后一行不是重载之一,它描述了实现的参数。有时你会看到 any
,但你也可以在这里使用并集。
function overloaded(a: string): string
function overloaded(a: number): number
function overloaded(a: any): any {
return a;
}
不同的参数 return 基于它们匹配的重载的特定类型。
const oNum: number = overloaded(0);
const oStr: string = overloaded("");
const oBool = overloaded(true); //error
在我们的联合中,两种输入类型都只是 return 联合,所以我们失去了特异性。
function union(a: string | number): string | number {
return a;
}
const uNum: string | number = union(0);
const uStr: string | number = union("");
const uBool = union(true); //error
还有第三个选项typescript generics。这使我们能够在接受无限多种类型的同时保持特异性。 boolean
示例现在可以使用了。我们告诉打字稿“查看参数的类型 a
并调用它 T
”。然后我们得到这个类型变量 T
,我们可以在 return 类型中使用它。在这里我们只是直接 returning 相同的类型 T
,但是你可以用它做很多事情。
function generic<T>(a: T): T {
return a;
}
const gNum: number = generic(0);
const gStr: string = generic("");
const gBool: boolean = generic(true);
只是扩展@Linda Paiste 关于泛型类型的评论
const gNum: number = generic(0);
这基本上就是在说
function generic<0>(a: 0): 0;
有时这可能不是您想要的。所以在使用泛型的时候,要传入一个类型参数:
const gNum: number = generic<number>(0);
对于函数参数类型,函数重载可以比联合类型和泛型类型更具体。
现实世界的例子:
createActivity
函数用于创建三种输入参数不同的活动。 CreateRenewalActivityParams
、CreateInsureActivityParams
和 CreateTrafficGenerationActivityParams
。
interface CreateActivityParams {
activityCode: string;
activityName: string;
activityDesc: string;
activityType: number;
activityTypeName: string;
startTime: string;
endTime: string;
paymentType: string | null;
}
interface CreateRenewalActivityParams extends CreateActivityParams {
installmentCases: any[];
}
interface CreateInsureActivityParams extends CreateActivityParams {
cases: any[];
}
interface CreateTrafficGenerationActivityParams extends CreateActivityParams {
cases: any[];
}
export async function createActivity(data: CreateTrafficGenerationActivityParams): Promise<boolean>;
export async function createActivity(data: CreateInsureActivityParams): Promise<boolean>;
export async function createActivity(data: CreateRenewalActivityParams): Promise<boolean>;
export async function createActivity(data: CreateActivityParams): Promise<boolean> {
return true;
}
// TSC throw error
createActivity({
activityCode: 'test code',
activityName: 'test name',
activityDesc: 'test desc',
activityType: 8,
activityTypeName: 'test type name',
startTime: '2021-07-20 00:00:00',
endTime: '2025-07-20 23:59:59',
paymentType: null,
cases: [
{
pictureCode: 'test pic code',
authDesc: null,
},
{
pictureCode: 'test pic code',
authDesc: null,
},
],
installmentCases: [],
});
export async function createActivityUnion(data: CreateTrafficGenerationActivityParams | CreateInsureActivityParams | CreateRenewalActivityParams) {
return true;
}
// TSC pass
createActivityUnion({
activityCode: 'test code',
activityName: 'test name',
activityDesc: 'test desc',
activityType: 8,
activityTypeName: 'test type name',
startTime: '2021-07-20 00:00:00',
endTime: '2025-07-20 23:59:59',
paymentType: null,
cases: [
{
pictureCode: 'test pic code',
authDesc: null,
},
{
pictureCode: 'test pic code',
authDesc: null,
},
],
installmentCases: [],
});
export async function createActivityGeneric<Data extends CreateActivityParams>(data: Data) {
return true;
}
// TSC pass
createActivityGeneric({
activityCode: 'test code',
activityName: 'test name',
activityDesc: 'test desc',
activityType: 8,
activityTypeName: 'test type name',
startTime: '2021-07-20 00:00:00',
endTime: '2025-07-20 23:59:59',
paymentType: null,
cases: [
{
pictureCode: 'test pic code',
authDesc: null,
},
{
pictureCode: 'test pic code',
authDesc: null,
},
],
installmentCases: [],
})
现在,我们希望函数的参数在同时包含installmentCases
和cases
字段时报类型不兼容错误,因为它们属于不同的activity类型,可以是使用函数重载完成。
我们可以为 createActivity
函数编写三个更具体的重载签名,其中包含上述三种参数类型和 CreateActivityParams
类型的通用实现签名。