Typescript:基于参数props的条件返回类型



我有一个函数,我希望它根据它的参数props返回2种不同的类型。

interface IPaginateParams {
perPage: number;
currentPage: number;
isFromStart?: boolean;
}
interface IWithPagination<Data, TParams extends IPaginateParams = IPaginateParams> {
data: Data;
pagination: IPagination<TParams>;
}
type IPagination<TParams> = TParams extends
| { currentPage: 1 }
| { isFromStart: true }
| { isLengthAware: true }
? ILengthAwarePagination
: IBasePagination;
interface IBasePagination {
currentPage: number;
perPage: number;
from: number;
to: number;
}
interface ILengthAwarePagination extends IBasePagination {
total: number;
lastPage: number;
}
function paginate<TData = any[], TParams extends IPaginateParams = IPaginateParams>(
options: TParams
): IWithPagination<TData, TParams>;

这个想法是,如果您传递currentPage: 1isFromStart: true,它应该向pagination对象添加2个额外的类型。

奇怪的是IWithPagination按预期工作,

const data = {} as IWithPagination<any, {perPage: 2, currentPage: 1}>;
expectType<ILengthAwarePagination>(data.pagination);

但是当我使用调用时,它总是返回IBasePagination

const data = paginate({perPage: 2, currentPage: 1});
expectType<ILengthAwarePagination>(data.pagination) // fails
// or
const data = paginate({perPage: 2, currentPage: 2, isFromStart: true});
expectType<ILengthAwarePagination>(data.pagination) // fails

游乐场

正如@OlegValter在评论中解释的那样,当将对象传递给paginate时,它推断为宽类型,例如:

{perPage: 2, currentPage: 2, isFromStart: true} // inferred as {perPage: number; currentPage: number; isFromStart: boolean}

因此,检查返回类型总是回退到IBasePagination类型(else子句)。

我们所需要做的就是指定函数的实参为readonly

declare function paginate<TData = any[], TParams extends IPaginateParams = IPaginateParams>(
options: Readonly<TParams>
// ---------^ this is what made the input as a narrow type
): IWithPagination<TData, TParams>;

工作示例

最新更新