Я создал эту игровую площадку , которая иллюстрирует проблему, и вот код:
export enum TransformerActions {
Delete = 'delete',
}
type FilteredKeys<T, U> = { [P in keyof T]: T[P] extends keyof TransformerActions ? never : T[P] extends U ? P : never }[keyof T];
type Fn = (...args: any[]) => any;
export type Transformed<S, M> = {
[P in FilteredKeys<S, M>]: S[P] extends Fn ? ReturnType<S[P]> : never;
};
export const objectMapper = <S, M extends Transformed<S, M>>(
source: S,
map: M
): Transformed<S, M> => {
const result: TransformerMap<S> = {};
for (const k of Object.keys(source)) {
if(!map[k]) {
continue;
}
const value = source[k];
if (map?.[k] === TransformerActions.Delete) {
continue;
}
if (typeof map?.[k] === 'function') {
result[k] = transform(map[k](source));;
continue;
}
result[k] = value;
}
return result;
}
const source = {
firstName: 'Paul',
surname: 'Cowan',
age: 50,
address: 'somewhere in nowhere'
};
type Source = typeof source
const map = {
address: TransformerActions.Delete,
name: (n: Source) => `${n.firstName} ${n.surname}`
}
const result = objectMapper(source, map)
/* should be
{
name: string
}
I don't think filtering on enum is possible but not sure why the ReturnType is not working
*/
В основном у меня есть функция objectTransformer
, и я хочу использовать условные типы для фильтрации из всех полей, возвращающих специфицированное c перечисление, или если поле является функцией, то я хочу, чтобы это поле возвращало ReturnType
функции, а не саму функцию
const map = {
address: TransformerActions.Delete,
name: (n: Source) => `${n.firstName} ${n.surname}`
}
Ни одно из условий не работает для меня прямо сейчас :).