[英]In TypeScript, how do I make a function's return type based on the return type of one of its arguments?
[英]Make return type of function depends on its arguments with TypeScript?
我有一个函数返回一个承诺,它可以是两种类型之一:
async profilesAll(
ids: readonly number[],
profileType: ProfileType.Staff | ProfileType.Pupil,
): Promise<(DatabaseSchema.staffProfiles | DatabaseSchema.pupilProfiles)[]> {
// lots of logic here
}
在其他地方我正在调用这个函数。 otherFunction
的返回类型是一个DatabaseSchema.pupilProfiles
数组
const otherFunction = () => {
const results = await ctx.models.room.profilesAll(
[root.id],
ProfileType.Pupil,
);
return results;
}
TypeScript 会抛出错误,因为它认为返回类型可以是DatabaseSchema.staffProfiles
或DatabaseSchema.pupilProfiles
。 然而实际上, profilesAll
的逻辑阻止了这一点。
我怎样才能消除这个错误? 我可以让profilesAll
的返回类型取决于profileType
参数吗? 我查看了条件类型,但我只能看到它们扩展类型的示例,而不是根据需要使用函数参数。
您应该使用重载:
async function profilesAll(ids: number[], profileType: ProfileType.Pupil): Promise<(DatabaseSchema.pupilProfiles)[]>
async function profilesAll(ids: number[], profileType: ProfileType.Staff): Promise<(DatabaseSchema.staffProfiles)[]>
async function profilesAll(
ids: readonly number[],
profileType: ProfileType.Staff | ProfileType.Pupil,
): Promise<DatabaseSchema.staffProfiles[]> | Promise<DatabaseSchema.pupilProfiles[]> {
// lots of logic here
}
我认为您不能根据输入参数动态修改返回类型。 但是,在这种特定情况下,您可以通过显式定义来指定otherFunction
的返回类型。
const otherFunction = (): DatabaseSchema.pupilProfiles => { ... }
这样你的otherFunction
返回类型不再是DatabaseSchema.staffProfiles | DatabaseSchema.pupilProfiles
DatabaseSchema.staffProfiles | DatabaseSchema.pupilProfiles
但仅限DatabaseSchema.pupilProfiles
。
您可以为此声明使用函数/方法重载。
class Foo {
//option 1:
async profilesAll(ids: readonly number[], profileType: ProfileType.Staff): Promise<DatabaseSchema.staffProfiles[]>;
//option 2:
async profilesAll(ids: readonly number[], profileType: ProfileType.Pupil): Promise<DatabaseSchema.pupilProfiles[]>;
//implementation:
async profilesAll(ids: readonly number[], profileType: ProfileType.Staff | ProfileType.Pupil): Promise<(DatabaseSchema.staffProfiles | DatabaseSchema.pupilProfiles)[]> {
if (profileType === ProfileType.Staff) return getStaff(ids);
return getPupils(ids);
}
}
请注意,您首先需要重载签名,然后第三个实现签名应该是它们的合并。 在此处查看有关重载的更多信息。
这将允许您进行类型安全调用:
declare const instance: Foo;
//OK:
const pupils = await instance.profilesAll([1, 2, 3], ProfileType.Pupil);
//OK:
const staff = await instance.profilesAll([1, 2, 3], ProfileType.Staff);
//Error - return type is not pupilProfiles:
const wrong: DatabaseSchema.pupilProfiles[] = await instance.profilesAll([1, 2, 3], ProfileType.Staff);
使用函数并重载它们是类似的,但在这种情况下你不会有一个类:
//option 1:
async function profilesAll(ids: readonly number[], profileType: ProfileType.Staff): Promise<DatabaseSchema.staffProfiles[]>;
//option 2:
async function profilesAll(ids: readonly number[], profileType: ProfileType.Pupil): Promise<DatabaseSchema.pupilProfiles[]>;
//implementation:
async function profilesAll(ids: readonly number[], profileType: ProfileType.Staff | ProfileType.Pupil): Promise<(DatabaseSchema.staffProfiles | DatabaseSchema.pupilProfiles)[]> {
if (profileType === ProfileType.Staff) return getStaff(ids);
return getPupils(ids);
}
/* ... */
//OK:
const pupils = await profilesAll([1, 2, 3], ProfileType.Pupil);
//OK:
const staff = await profilesAll([1, 2, 3], ProfileType.Staff);
//Error - return type is not pupilProfiles:
const wrong: DatabaseSchema.pupilProfiles[] = await profilesAll([1, 2, 3], ProfileType.Staff);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.