[英]Make return type of function depends on its arguments with TypeScript?
I have a function that returns a promise which can be either of 2 types:我有一个函数返回一个承诺,它可以是两种类型之一:
async profilesAll(
ids: readonly number[],
profileType: ProfileType.Staff | ProfileType.Pupil,
): Promise<(DatabaseSchema.staffProfiles | DatabaseSchema.pupilProfiles)[]> {
// lots of logic here
}
Elsewhere I'm calling this function.在其他地方我正在调用这个函数。
otherFunction
's return type is an array of DatabaseSchema.pupilProfiles
otherFunction
的返回类型是一个DatabaseSchema.pupilProfiles
数组
const otherFunction = () => {
const results = await ctx.models.room.profilesAll(
[root.id],
ProfileType.Pupil,
);
return results;
}
TypeScript throws an error as it believes the return type can be DatabaseSchema.staffProfiles
or DatabaseSchema.pupilProfiles
. TypeScript 会抛出错误,因为它认为返回类型可以是
DatabaseSchema.staffProfiles
或DatabaseSchema.pupilProfiles
。 However in reality the logic within profilesAll
prevents this.然而实际上,
profilesAll
的逻辑阻止了这一点。
How can I remove this error?我怎样才能消除这个错误? Can I make
profilesAll
's return type depend on the profileType
argument?我可以让
profilesAll
的返回类型取决于profileType
参数吗? I looked at conditional types but I can only see examples of them extending types, not using function arguments as I need.我查看了条件类型,但我只能看到它们扩展类型的示例,而不是根据需要使用函数参数。
You should use overloads:您应该使用重载:
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
}
I don't think you can modify the return type based on the input parameter dynamically.我认为您不能根据输入参数动态修改返回类型。 However, in this specific case, you can specify the return type of your
otherFunction
by explicitly defining it.但是,在这种特定情况下,您可以通过显式定义来指定
otherFunction
的返回类型。
const otherFunction = (): DatabaseSchema.pupilProfiles => { ... }
This way your otherFunction
return type is no longer DatabaseSchema.staffProfiles | DatabaseSchema.pupilProfiles
这样你的
otherFunction
返回类型不再是DatabaseSchema.staffProfiles | DatabaseSchema.pupilProfiles
DatabaseSchema.staffProfiles | DatabaseSchema.pupilProfiles
but DatabaseSchema.pupilProfiles
only. DatabaseSchema.staffProfiles | DatabaseSchema.pupilProfiles
但仅限DatabaseSchema.pupilProfiles
。
You can use function/method overloading for this declaration.您可以为此声明使用函数/方法重载。
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);
}
}
Note that you need the overloaded signatures first, then and the third implementation signature should be a merge of them.请注意,您首先需要重载签名,然后第三个实现签名应该是它们的合并。 See more on overloading here .
在此处查看有关重载的更多信息。
This will then allow you to make type safe calls:这将允许您进行类型安全调用:
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);
Using functions and overloading them, is analogous but you wouldn't have a class in that case:使用函数并重载它们是类似的,但在这种情况下你不会有一个类:
//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.