我不会创建用于验证对象的通用函数。 我希望它接受以下签名的选项对象:
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]
])
}
答案 0 :(得分:3)
如果意图只是保存基于字符串的键的值,我强烈建议您放弃使用Map
。这就是一个普通的旧对象的用途。重要的是,对于TypeScript,基于对象的类型有很多支持,您可以通过mapped type轻松表示validators
所期望的行为,如下所示:
export interface ValidationOptions<T> {
validators: { [K in keyof T]?: (value: T[K]) => string | null }
}
const options: ValidationOptions<ObjectToValidate> = {
validators: {
stringy: fooValidator
}
}
如果由于某种原因您需要继续使用Map
,则内置TypeScript typings将不起作用,因为它们的作用更像是一个记录类型,其中每个键都是K
,每个值都是V
,并且两种类型是独立的。可以代表一种称为ObjectMap
的新类型,其类型基于键和值之间的潜在关系,但是要想知道要去哪里,要进行很多类型的调整。
希望有所帮助;祝你好运!