英文:
Exclude utility does not work in mapped types
问题
需要排除某些字面值以用于映射类型:
type ReformValidator = "required" | "minLength" | "maxLength";
interface FieldsValidator {
[key: string]: {
[V in ReformValidator]?: any
} & {
[K in Exclude<string, ReformValidator>]?: {
validator: () => boolean;
message: string;
}
}
}
const validators: FieldsValidator = {
firstName: {
required: true
}
}
期望没有错误,但出现了以下错误:
类型 '{ required: true; }' 不能赋值给类型 '{ required?: any; } ... } & { [x: string]: { ... }; }'。
- 类型 '{ required: true; }' 不能赋值给类型 '{ ... }; }'。
- 属性 'required' 与索引签名不兼容。
- 类型 'boolean' 不能赋值给类型 '{ validator: () => boolean; message: string; }'
- 属性 'required' 与索引签名不兼容。
英文:
I need exclude some literals for a mapped type:
type ReformValidator = "required" | "minLength" | "maxLength";
interface FieldsValidator {
[key: string]: {
[V in ReformValidator]?: any
} & {
[K in Exclude<string, ReformValidator>]?: {
validator: () => boolean;
message: string;
}
}
}
const validators: FieldsValidator = {
firstName: {
required: true
}
}
Expecting no error, but has:
Type '{ required: true; }' is not assignable to type '{ required?: any; ... } & { [x: string]: { ... }; }'.
- Type '{ required: true; }' is not assignable to type '{ ... }; }'.
- Property 'required' is incompatible with index signature.
- Type 'boolean' is not assignable to type '{ validator: () => boolean; message: string; }'
- Property 'required' is incompatible with index signature.
答案1
得分: 0
Sure, here's the translated content:
首先,如果你不想将 { validator: () => boolean; message: string; }
分配给 ReformValidator 中的键,你必须限制它的类型。它不能是 any
,因为 { validator: () => boolean; message: string; }
满足 any
。我建议使用更具体的类型,比如 boolean | number
。
其次,将 &
替换为 |
,就完成了。
interface FieldsValidator {
[key: string]: {
[V in ReformValidator]?: boolean;
} | {
[K: string]: {
validator: () => boolean;
message: string;
}
}
}
你可以去掉 [K: string]?
中的 ?
,因为如果 Record
的键是 string
,那么值不是具体的,所以它们不是必需的。
你甚至可以使用内置类型更进一步简化声明:
type FieldsValidator = Record<
string,
Partial<Record<ReformValidator, boolean | number>>
| Record<string, {
validator: () => boolean;
message: string
}>
>;
这意味着:
Record<K, V>
等同于{ [key: K]: V }
Partial<K>
使K
中的所有键变成可选的(带有?
),因此Partial<Record<K, V>>
等同于{ [key: K]?: V }
英文:
First, if you don't want to be able to assign { validator: () => boolean; message: string; }
to keys within ReformValidator, you have to restrict its type. It cannot be any
, because { validator: () => boolean; message: string; }
satisfies any
. I'd suggest a more concrete type like boolean | number
.
Second, replace &
with |
and there you go.
interface FieldsValidator {
[key: string]: {
[V in ReformValidator]?: boolean;
} | {
[K: string]: {
validator: () => boolean;
message: string;
}
}
}
You can get rid of ?
in [K: string]?
, because if the key of Record
is string
, then the values are not concrete, so they are not needed.
You can simplify the declaration even more by using built-in types:
type FieldsValidator = Record<
string,
Partial<Record<ReformValidator, boolean | number>>
| Record<string, {
validator: () => boolean;
message: string
}>
>;
Which means:
Record<K, V>
is equivalent to{ [key: K]: V }
Partial<K>
makes all keys inK
optional (with?
), soPartial<Record<K, V>>
is equivalent to{ [key: K]?: V }
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论