Можно ли типизировать не приводя к типу Getter?
Требования:
- Key должен быть типизирован, то есть нельзя указать key, который не принадлежит объекту
- Возвращаемое значение (одиночное значение или массив) должно на уровне типов конкретизироваться через параметр isIncludeKey.
Sandbox
type ObjectType = Record<string, unknown>;
type OnlyString<T> = T extends string ? T : never;
type GetObjectKeys<T extends ObjectType> = OnlyString<keyof T>;
type GetObjectValues<T extends ObjectType> = T[GetObjectKeys<T>];
type Getter<T extends ObjectType, Flag extends boolean> = (
key: GetObjectKeys<T>
) => Flag extends true ? Array<GetObjectValues<T>> : GetObjectValues<T>;
const getValue =
<TTargetObject extends ObjectType, TFlag extends boolean>(
obj: TTargetObject,
isIncludeKey?: TFlag
): Getter<TTargetObject, TFlag> =>
(key) => {
if (!isIncludeKey) {
return obj[key];
}
return Object.entries(obj).reduce<GetObjectValues<TTargetObject>[]>(
(result, pair) => {
const [pairKey, pairValue] = pair;
if (pairKey.includes(key)) {
return [...result, pairValue] as GetObjectValues<TTargetObject>[];
}
return result;
},
[]
);
};
const getter = getValue({ a: 1, b: 2, c: 3, d: 4, e: 5 }, true);
console.log(getter("a"));
/*
Type '(key: OnlyString<keyof TTargetObject>) => TTargetObject[OnlyString<keyof TTargetObject>] | GetObjectValues<TTargetObject>[]' is not assignable to type 'Getter<TTargetObject, TFlag>'.
*/