我正在尝试创建名为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
答案 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',
},
};