Я пытаюсь создать функцию обновления, которая обновляет глубокие значения в записи. У меня есть перегруженные варианты для путей различной глубины.
Я не могу понять, как правильно ввести функцию обратного вызова, используемую для обновляемого значения.
interface Test {
foo?: { bar: number }
}
const input: Test = { foo: { bar: 1 } }
update(input, 'foo', 'bar')(v => v + 1)
Когда яиспользуйте функцию, она говорит мне, что «Object (v) имеет тип unknown».
Но, например, у меня есть похожая функция set, она определена почти так же, но она правильно печатается при использовании следующим образом:
set(input, 'foo', 'bar')(2)
Вот моя функция
type UpdateFn<T> = (value: T) => T
export function update<T extends Record<string, any>, K1 extends keyof T>(
record: T | undefined,
key1: K1
): (callback: UpdateFn<NonNullable<T[K1]>>) => T
export function update<
T extends Record<string, any>,
K1 extends keyof T,
K2 extends keyof NonNullable<T[K1]>
>(
record: T | undefined,
key1: K1,
key2: K2
): (callback: UpdateFn<NonNullable<T[K1][K2]>>) => T
export function update<
T extends Record<string, any>,
K1 extends keyof T,
K2 extends keyof NonNullable<T[K1]>
>(
record: T | undefined,
key1: K1,
key2?: K2
): (
callback:
| UpdateFn<NonNullable<T[K1]>>
| UpdateFn<NonNullable<T[K1][K2]>>
) => T | undefined {
return callback => {
if (record === undefined) return record
if (key2 === undefined) {
const value = get(record, key1)
if (value === undefined) return record
return set(record, key1)(callback(value))
} else {
const value = get(record, key1, key2)
if (value === undefined) return record
return set(record, key1, key2)(callback(value))
}
}
}
Установить (работает правильно):
export function set<
T extends Record<string, any>,
K1 extends keyof T,
K2 extends keyof NonNullable<T[K1]>
>(record: T | undefined, key1: K1, key2: K2): (value: T[K1][K2]) => T