Description
When using R.sortBy (data-first or data-last), TypeScript fails to resolve the input type when it receives a Mapped<T, K> (the return type of R.map) where T originates from TypeScript's built-in NoInfer<T>.
The Mapped type ({ -readonly [P in keyof T]: K }) works fine for standard array methods (.find(), .map()), but R.sortBy's T extends IterableContainer generic constraint can't unify Mapped<NoInfer<...>, K> with IterableContainer.
Minimal reproduction
import * as R from "remeda";
declare function getData<TData>(options: {
select: (raw: { items: Array<{ type: string; name: string }> }) => TData;
}): { data: NoInfer<TData> | undefined };
const { data } = getData({
select: (raw) => raw.items,
});
// ✅ R.map result works fine on its own — Mapped<T, K> resolves for .find()
const mapped = R.map(data ?? [], (item) => ({ ...item, extra: true }));
mapped.find((r) => r.type === "a"); // OK
// ❌ Passing that same Mapped<T, K> into R.sortBy fails
const sorted = R.sortBy(mapped, (item) => item.name);
sorted.find((r) => r.type === "a"); // Error: This expression is not callable
// ❌ R.pipe + data-last also fails
const piped = R.pipe(
data ?? [],
R.map((item) => ({ ...item, extra: true })),
R.sortBy((item) => item.name),
);
piped.find((r) => r.type === "a"); // Error: This expression is not callable
// ✅ Native .map result (plain Array<K>) works with R.sortBy
const nativeMapped = (data ?? []).map((item) => ({ ...item, extra: true }));
const sorted2 = R.sortBy(nativeMapped, (item) => item.name);
sorted2.find((r) => r.type === "a"); // OK
// ✅ Explicit Array annotation on the intermediate also works
const explicit: Array<{ type: string; name: string; extra: boolean }> =
R.map(data ?? [], (item) => ({ ...item, extra: true }));
const sorted3 = R.sortBy(explicit, (item) => item.name);
sorted3.find((r) => r.type === "a"); // OK
Context
This became an issue after @tanstack/react-query v5.100.13 switched from a custom NoInfer implementation to TypeScript's built-in NoInfer intrinsic in TanStack/query#10593. useQuery's return type wraps TData in NoInfer, so any data flowing through R.map → R.sortBy breaks.
Workarounds
- Use native
.map() before R.sortBy (returns plain Array<K> instead of Mapped<T, K>)
- Store
R.map result with an explicit Array<...> type annotation
Environment
- remeda: 2.37.0
- TypeScript: 5.9.3
Description
When using
R.sortBy(data-first or data-last), TypeScript fails to resolve the input type when it receives aMapped<T, K>(the return type ofR.map) whereToriginates from TypeScript's built-inNoInfer<T>.The
Mappedtype ({ -readonly [P in keyof T]: K }) works fine for standard array methods (.find(),.map()), butR.sortBy'sT extends IterableContainergeneric constraint can't unifyMapped<NoInfer<...>, K>withIterableContainer.Minimal reproduction
Context
This became an issue after
@tanstack/react-queryv5.100.13 switched from a customNoInferimplementation to TypeScript's built-inNoInferintrinsic in TanStack/query#10593.useQuery's return type wrapsTDatainNoInfer, so any data flowing throughR.map→R.sortBybreaks.Workarounds
.map()beforeR.sortBy(returns plainArray<K>instead ofMapped<T, K>)R.mapresult with an explicitArray<...>type annotationEnvironment