У меня проблемы с написанием правильных типов для простой функции.
Я хочу создать функцию, которая при получении клавиши (keyof any
) или обратного вызова будет возвращать другую функцию. Эта функция принимает некоторые данные и возвращает другую клавишу.
Другими словами, toKey('propertyName')
и toKey(value => value.propertyName)
будут возвращать функцию value => value.propertyName
. При вызове функция возвращает указанное значение указанного свойства, только если значение имеет тип string
, number
или symbol
.
Вот пример:
function toKey(keyIdentity) { /* snippet */ }
interface IPerson {
firstName: string,
lastName: string,
age: number,
emails: string[]
};
const getKey1 = toKey((person: IPerson) => person.emails[0]);
const getKey2 = toKey('firstName');
const getKey3 = toKey('emails');
const person: IPerson = {
firstName: 'Craig',
lastName: 'Lipton',
age: 46,
emails: [
'<email-1>',
'<email-2>'
]
};
getKey1(person); // returns "<email-1>";
getKey2(person); // returns "Craig";
getKey3(person); // not allowed;
Я пытался использовать дженерики и перегрузки для достижения правильной типизации, но это очень быстро усложняется.
function toKey(key?: null): () => void;
function toKey<K extends keyof any>(key: K): <U extends keyof any>(item: Record<K, U>) => U;
function toKey<T extends (...args: any[]) => keyof any>(key: T): T;
function toKey(key: any): any {
if (isNil(key)) {
return noop;
}
return isFunction(key) ? key : (value: T) => value[key];
}
Есть ли более простой способ написать это?