I have a function that should return two different types based on its argument props.
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>;
The concept is that if you specify currentPage: 1
or isFromStart: true
, it should include two additional types in the pagination
object.
Interestingly, IWithPagination
behaves as intended,
const data = {} as IWithPagination<any, {perPage: 2, currentPage: 1}>;
expectType<ILengthAwarePagination>(data.pagination);
However, when using the function, it always returns the 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