打字稿。在表单结构中键入键值对

时间:2017-03-03 11:16:52

标签: typescript typing

我正在输入一个效果很好的表单结构。然而,在字段中的表单字段的验证部分中发生了一些有趣的事情。

我的Visual Code会告诉我phone常量中的'required2'验证不正确,因为它必须是'required'。 但是,当您查看form常量的字段集合中的phonefield项时,不抱怨required2是不允许的。 只有当我在界面中提供required时,表单常量才会无效。

我的目标是限制每个表单字段的验证,以便某人无法将键/值添加到未键入的验证字典中。

有趣的是,当我将phonenumber更改为phonenumber2时,输入将是不正确的。但是,更改所需的密钥并不重要,因为它不是必需的。

我的界面

declare type fields           = IPhoneField | ISelectField ..etc;

export interface IPage {
  title?:               string;
  buttons?:             IButton[];
  fields:               fields[];
  showOn?:              IDictionary <string | number>;
}

export interface IForm {
  modelPreset:          IDictionary <string | number>;
  successPageConfig?:   IDictionary <string | number | boolean>;
  presentation:         pagePresentation;
  pages:                IPage[];
}

interface IField {

  label:                string;
  model:                string;
  placeholder?:         string;
  addon?:               string;
  showOn?:              IDictionary <string | number>;
  maxlength?:           number;

}

export interface IPhoneField extends IField {
  type:                 'phone';
  validation:    {
    required?:          string;
    phonenumber:        string;
  };
}

我的代码

const phone: IPhoneField = {
  "label":"Phone Number",
  "model":"phonenumber",
  "type":"phone",
  "placeholder":"Phone number",
  "validation":{
      "required2":"A phone number is required",
      "phonenumber":"Please enter a valid phone number",

    }
};

const form: IDictionary<IForm> = {
  "form1":{
      "pages":[
        {
            "fields": [
              {
                  "label":"Phone Number",
                  "model":"phonenumber",
                  "type":"phone",
                  "placeholder":"Phone number",
                  "validation":{
                    "required2":"A phone number is required",
                    "phonenumber":"Please enter a valid phone number"
                  }
              }
            ]
        }
      ]
  }
};

有谁知道为什么会这样?这是打字稿的错误吗?

请参阅游乐场链接: NEW playground

1 个答案:

答案 0 :(得分:0)

它不是TypeScript中的错误。您正在创建与其签名不同类型的对象,因此类型推断无效。

首先:required2上的phone不允许validation,因为它是一个无关的字段。它与现有的required?字段没有任何关系。由于您正在使用类型推断,因此即使对象仍满足接口,添加字段也会导致推断类型不同。

如果您真的想这样做,可以将其标记为该类型。由于您没有界面或类型名称,因此您必须这样做:

const phone: IPhoneField = {
  "label":"Phone Number",
  "model":"phonenumber",
  "type":"phone",
  "placeholder":"Phone number",
  "validation":{
    "required2":"A phone number is required",
    "phonenumber":"Please enter a valid phone number",
  } as { required?: string, phonenumber: string},
};

但当然最好这样做:

interface IPhoneValidation {
  required?:          string;
  phonenumber:        string;
}

export interface IPhoneField extends IField {
  type:                 'phone';
  validation:           IPhoneValidation;
}

const phone: IPhoneField = {
  "label":"Phone Number",
  "model":"phonenumber",
  "type":"phone",
  "placeholder":"Phone number",
  "validation":{
    "required2":"A phone number is required",
    "phonenumber":"Please enter a valid phone number",
  } as IPhoneValidation,
}

现在,为什么它不抱怨表单中的错误。这是因为您的表单的验证字段根本没有进行类型检查。

由于您尚未发布IDictionary实施内容,因此需要进行一些猜测以确定原因。但是有一个样本字典实现:

interface IDictionary<T> {
  [K: string]: T;
}

我在form声明中收到错误,因此无法分配。重要的是要注意错误不会来自required2,原因很简单,因为您正在编写一组深层次的无类型对象,并且仅将它们分配给form。结束,并注意到无效的分配。您可以阅读错误消息,然后您就会看到它。我明白了:

Type '{ "form1": { "pages": { "fields": { "label": string; "model": string; "type": "phone"; "placehold...' is not assignable to type 'IDictionary<IForm>'.
  Property '"form1"' is incompatible with index signature.
    Type '{ "pages": { "fields": { "label": string; "model": string; "type": "phone"; "placeholder": string...' is not assignable to type 'IForm'.
      Property 'modelPreset' is missing in type '{ "pages": { "fields": { "label": string; "model": string; "type": "phone"; "placeholder": string...'.

这是一个满口(并且被夹住),但有些表明内心存在错误。

如果在分配期间键入对象,则会更早地收到错误,因此更容易解析,或者如果对象满足界面则根本不会得到它们。例如:

const form: IDictionary<IForm> = {
    "form1": {
        "pages": [
            {
                "fields": [
                    {
                        "label": "Phone Number",
                        "model": "phonenumber",
                        "type": "phone",
                        "placeholder": "Phone number",
                        "validation": {
                            "required2": "A phone number is required",
                            "phonenumber": "Please enter a valid phone number"
                        } as IValidation,
                    } as IField,
                ]
            } as IPage,
        ]
    }
};

在上述情况下,一切都会正常,否则当它们存在时你会看到错误。

TypeScript执行所有这些检查并且不会自动将某些内容类型化为具有无关字段的接口的原因是要避免输入错误。如果它确实允许任何内容,您可以输入requird,但从未意识到它不是required,因为它是一个可选字段。换句话说,{required2: ..., phonenumber: ...} 允许作为validation对象,但不会在没有类型注释的情况下自动识别

如果您希望接口自动允许其他属性,您可以执行以下操作:

interface IValidation {
  required?:          string;
  phonenumber:        string;
  [propName:string]:  any;
}

了解&#34;多余的财产检查&#34; in the interface manual了解更多相关信息。