类型声明对象文字打字稿

时间:2019-11-26 20:39:00

标签: reactjs typescript type-assertion

我正在尝试创建名为fields类型为Fields的对象的对象。该对象包含类型为FieldTypes的对象,该对象接收通用类型并返回另一种类型。

创建对象fields

export const fields = {
  name: {
    label: 'Name',
    type: 'text',
  } as TextType,
};

我的类型文件

export interface Fields {
  [name: string]: FieldTypes;
}

export type Types = 'text' | 'select' | 'checkbox' | 'email' | 'number';

export type ValidationTypes = Yup.MixedSchema | Yup.StringSchema |
  Yup.NumberSchema | Yup.BooleanSchema |
  Yup.DateSchema | Yup.ArraySchema<{}> | Yup.ObjectSchema;

export interface FieldType {
  label: string;
  type: Types;
  initialValue: any;
  validation: ValidationTypes;
  placeholder?: string;
}

export interface TextType extends FieldType { }
export interface EmailType extends FieldType { }
export interface NumberType extends FieldType { }
export interface CheckboxType extends FieldType, CheckboxInterface { }
export interface SelectType extends FieldType {
  options?: Option[];
}

export type FieldTypes = TextType | EmailType | SelectType | CheckboxType | NumberType;

我面临的问题是,当我将对象name创建为TextType时,我期望Typescript会显示类似Object name is missing initialValues and validation properties的错误,因为它已被声明在TextType界面上。

我发现它起作用的唯一方法是定义一个名为FieldName的变量,并将其赋予字段之外的属性,例如:

const NameField: TextType = {
  initialValue: '',
};

以这种方式创建对象时,出现错误Type '{ initialValue: string; }' is missing the following properties from type 'TextType': label, type, validation

2 个答案:

答案 0 :(得分:0)

您使用TypeScript的断言功能错误。断言有一些非常特殊的用例,不应用于声明常规的ol'变量和类型。

https://basarat.gitbooks.io/typescript/docs/types/type-assertion.html#assertion-considered-harmful

  

TypeScript的类型断言纯粹是告诉编译器您对类型的了解要比对它的了解要好,并且它不应该再次猜测您。

     

...

     

但是,在使用断言时应该小心……编译器不会保护您避免忘记实际添加您所承诺的属性:

如果您希望对象的字段属于某种类型,则应明确声明它们:

const name: TextType = {
  label: 'Name',
  type: 'text',
};

export const fields: Fields = {
  name
};

这样,TypeScript会在您声明name的行上给您一个错误,因为它没有预期的形状TextType

还请注意,您应该声明fields的类型为Fields,因为否则TypeScript无法理解这是预期的类型。

答案 1 :(得分:0)

您的示例很好地展示了为什么,为什么显式类型注释应该比类型断言更可取。

  

我希望打字稿会显示类似Object name is missing validation的错误

Type assertions进行自己的兼容性检查,因此您不会意外地投射不兼容的类型,例如const t: string = 3 as string。但是它们比显式类型更宽松,并且将在两个方向上检查可分配性:从值/表达式到声明的类型,反之亦然!如果这些指示之一有效,则将编译代码。一个例子:

const withTypeAssertion = {
  label: 'Name',
  type: 'text',
} as TextType // compiles ?

有效。 { label: string, type: string}(扩展的string文字类型)不可分配/为TextType的子类型,但是TextType{ label: string, type: string}的子类型,因此它将编译! 使用显式类型,我们得到所需的错误:

const withExplicitType: TextType = {
  label: 'Name',
  type: 'text',
} // error ?

因此,从本质上讲,显式类型是可取的。例如,您可以使用以下类型注释fields

export const fields: Fields = {
  name: {
    label: 'Name',
    type: 'text',
  },
};

Playground