Exclude实用程序在映射类型中无法工作。

huangapple go评论66阅读模式
英文:

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; }'
英文:

I need exclude some literals for a mapped type:

type ReformValidator = &quot;required&quot; | &quot;minLength&quot; | &quot;maxLength&quot;;

interface FieldsValidator {
    [key: string]: {
        [V in ReformValidator]?: any
    } &amp; {
        [K in Exclude&lt;string, ReformValidator&gt;]?: {
            validator: () =&gt; 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; }'

答案1

得分: 0

Sure, here's the translated content:

首先,如果你不想将 { validator: () => boolean; message: string; } 分配给 ReformValidator 中的键,你必须限制它的类型。它不能是 any,因为 { validator: () => boolean; message: string; } 满足 any。我建议使用更具体的类型,比如 boolean | number

其次,将 &amp; 替换为 |,就完成了。

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
  }>
>;

这意味着:

  1. Record<K, V> 等同于 { [key: K]: V }
  2. Partial<K> 使 K 中的所有键变成可选的(带有 ?),因此 Partial<Record<K, V>> 等同于 { [key: K]?: V }
英文:

First, if you don't want to be able to assign { validator: () =&gt; boolean; message: string; } to keys within ReformValidator, you have to restrict its type. It cannot be any, because { validator: () =&gt; boolean; message: string; } satisfies any. I'd suggest a more concrete type like boolean | number.

Second, replace &amp; with | and there you go.

interface FieldsValidator {
    [key: string]: {
        [V in ReformValidator]?: boolean;
    } | {
        [K: string]: {
            validator: () =&gt; 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&lt;
  string, 
  Partial&lt;Record&lt;ReformValidator, boolean | number&gt;&gt;
  | Record&lt;string, {
    validator: () =&gt; boolean; 
    message: string
  }&gt;
&gt;;

Which means:

  1. Record&lt;K, V&gt; is equivalent to { [key: K]: V }
  2. Partial&lt;K&gt; makes all keys in K optional (with ?), so Partial&lt;Record&lt;K, V&gt;&gt; is equivalent to { [key: K]?: V }

huangapple
  • 本文由 发表于 2023年6月29日 17:50:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76579936.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定