为什么在TypeScript中,具有未定义值的记录类型应具有严格定义的字段?

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

Why Record type in TS with undefined as a value should have strictly defined fields?

问题

以下是您要翻译的内容:

实际上,我的问题与下面的情况相关:

我有一个用于表单值的类型
```typescript
interface FormValues {
  name: string
  description: string
  expirationDate: Date | null
}

以及一个用于在表单中存在错误时可以创建错误的类型

const errors: Record<keyof FormValues, string | undefined> = {
    name: undefined,
    description: undefined,
    expirationDate: undefined
}

然而,只有在我将每个字段定义为undefined时,错误类型才起作用,如果我尝试将其更改为空对象,那么TypeScript会返回错误

const errors: Record<keyof FormValues, string | undefined> = {}
/*
Type &#39;{}&#39; is missing the following properties 
from type &#39;Record<keyof FormValues, string | undefined>&#39;: name, description, expirationDate
*/

如何更改错误类型以反映我的需求,即将字段定义为字符串或不存在的对象:

const validate = values => {
  const errors: ??? = {}
  if (!values.name) errors.name = 'Required'
  if (!values.description) errors.description = 'Required'
  if (!values.expirationDate) errors.expirationDate = 'Required'
  return errors
}
英文:

Practically my question is related to a situation below:

I have a type for form values

interface FormValues {
  name: string
  description: string
  expirationDate: Date | null
}

and a type for errors that can be created if there are errors in a form

const errors: Record&lt;keyof FormValues, string | undefined&gt; = {
    name: undefined,
    description: undefined,
    expirationDate: undefined
}

however, the errors type works only if I define each fields as undefined, if I try to change it to an empty object, then TS responses with an error

const errors: Record&lt;keyof FormValues, string | undefined&gt; = {}
/*
Type &#39;{}&#39; is missing the following properties 
from type &#39;Record&lt;keyof FormValues, string | undefined&gt;&#39;: name, description, expirationDate
*/

how to change the error type to reflect my need in having an object with the fields defined as a string or non-exist:

const validate = values =&gt; {
  const errors: ??? = {}
  if (!values.name) errors.name = &#39;Required&#39;
  if (!values.description) errors.description = &#39;Required&#39;
  if (!values.expirationDate) errors.expirationDate = &#39;Required&#39;
  return errors
}

答案1

得分: 1

请看这个(你的类型):

type errorType1 = Record<keyof FormValues, string | undefined>;

等同于

type errorType1 = {
    name: string | undefined;
    description: string | undefined;
    expirationDate: string | undefined;
}

然后看看

type errorType2 = Partial<Record<keyof FormValues, string>>;

等同于

type errorType2 = {
    name?: string | undefined;
    description?: string | undefined;
    expirationDate?: string | undefined;
}

使用错误类型2,您可以忘记键。但使用第一个类型则不行。

您可能需要的是:

const errors: Partial<Record<keyof FormValues, string>> = {}
英文:

Take a look at this (your type) :

type errorType1 = Record&lt;keyof FormValues, string | undefined&gt;

wich is equivalent to

type errorType1 = {
    name: string | undefined;
    description: string | undefined;
    expirationDate: string | undefined;
}

Then look at

type errorType2 = Partial&lt;Record&lt;keyof FormValues, string&gt;&gt;

which is equivalent to

type errorType2 = {
    name?: string | undefined;
    description?: string | undefined;
    expirationDate?: string | undefined;
}

With error type 2, you are allowed to forget keys. With the first you can't.

What you need is probably :

const errors: Partial&lt;Record&lt;keyof FormValues, string&gt;&gt; = {}

答案2

得分: 1

您可以使用类型实用程序Partial<Type>来使类型的键变为可选的:

const errors: Partial<Record<keyof FormValues, string>> = {};

以下是一个完整的示例,基于您问题中的代码:

TS Playground

const formValueKeys = [
  "name",
  "description",
  "expirationDate",
] as const satisfies readonly (keyof FormValues)[];

const validate = (values: FormValues) => {
  const errors: Partial<Record<keyof FormValues, string>> = {};

  for (const key of formValueKeys) {
    if (!values[key]) errors[key] = "Required";
  }

  return errors;
};
英文:

You can use the type utility Partial&lt;Type&gt; to make the keys of a type optional:

const errors: Partial&lt;Record&lt;keyof FormValues, string&gt;&gt; = {};

Here's a complete example based on the code from your question:

TS Playground

const formValueKeys = [
  &quot;name&quot;,
  &quot;description&quot;,
  &quot;expirationDate&quot;,
] as const satisfies readonly (keyof FormValues)[];

const validate = (values: FormValues) =&gt; {
  const errors: Partial&lt;Record&lt;keyof FormValues, string&gt;&gt; = {};

  for (const key of formValueKeys) {
    if (!values[key]) errors[key] = &quot;Required&quot;;
  }

  return errors;
};

huangapple
  • 本文由 发表于 2023年2月8日 22:41:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/75387390.html
匿名

发表评论

匿名网友

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

确定