英文:
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 inKoptional (with?), soPartial<Record<K, V>>is equivalent to{ [key: K]?: V }
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论