Я не хочу создавать общую функцию для проверки объектов. Я хочу, чтобы он принимал объект параметров со следующей подписью:
export interface ValidationOptions<T, K extends keyof T = keyof T> {
validators: Map<K, (value: T[K]) => string | null>
}
Я хочу иметь возможность сопоставить K с массивом функций проверки, которые принимают аргумент типа T[K]. У меня проблема в том, что T[K] будет разрешать каждое возможное значение в T, а не конкретное значение для данного ключа.
Код ниже должен, надеюсь, пояснить, что я имею в виду.
export interface ValidationOptions<T, K extends keyof T = keyof T> {
validators: Map<K, (value: T[K]) => string | null>
}
function fooValidator(value: string) {
if (value === "foo") {
return "Value can't be foo"
}
return null;
}
function isNotTrueValidator(value: boolean) {
if (!value) {
return "Value must be true"
}
return null;
}
interface ObjectToValidate {
stringy: string;
booly: boolean;
}
//(value: T[K]) => string | null will resolve to value: string | boolean here
//Can i make it resolve to the type for the given property instead?
const options: ValidationOptions<ObjectToValidate> = {
//This results in an error with strictFunctionTypes enabled
validators: new Map([
//How can i
["stringy", fooValidator]
])
}
Я настоятельно рекомендую отказаться от использования Map
, если целью является просто хранение значений для строковых ключей. Вот для чего нужен старый добрый объект. Что важно для TypeScript, существует большая поддержка объектных типов, и вы можете легко представить поведение, которое вы ожидаете от validators
, с помощью отображаемый тип, например:
export interface ValidationOptions<T> {
validators: { [K in keyof T]?: (value: T[K]) => string | null }
}
const options: ValidationOptions<ObjectToValidate> = {
validators: {
stringy: fooValidator
}
}
Если по какой-то причине вам нужно продолжать использовать Map
, встроенный Типы TypeScript не будет работать, потому что они больше похожи на тип записи, где каждый ключ — K
, а каждое значение — V
, и эти два типа независимы. Можно представить новый тип с именем, скажем, ObjectMap
, типизация которого основана на лежащей в основе взаимосвязи между ключами и значениями, но это слишком много подтасовок типов, чтобы понять, куда вы идете.
Надеюсь, это поможет; удачи!
Спасибо, это работает отлично! Я начал с объектно-ориентированного подхода, но столкнулся с некоторыми проблемами с использованием keyof T в качестве подписи индекса, но, похоже, мне нужно прочитать сопоставленные типы. Еще раз большое спасибо!