![](/img/trans.png)
[英]Why does TypeScript assertion of object literal `{a}` work with interface `{a, b}` but not `{a?, b}`
[英]Type assertion object literal typescript
我試圖創建一個名為對象的對象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
Type '{ initialValue: string; }' is missing the following properties from type 'TextType': label, type, validation
您錯誤地使用了 TypeScript 的斷言功能。 斷言有一些非常具體的用例,它不應該用於聲明常規的 ol' 變量和類型。
https://basarat.gitbooks.io/typescript/docs/types/type-assertion.html#assertion-thinked-harmful
TypeScript 的類型斷言純粹是你告訴編譯器你比它更了解類型,並且它不應該猜測你。
...
但是,您應該小心使用斷言......編譯器不會保護您不會忘記實際添加您承諾的屬性:
如果您希望對象的字段屬於某種類型,那么您應該顯式聲明它們:
const name: TextType = {
label: 'Name',
type: 'text',
};
export const fields: Fields = {
name
};
這樣,TypeScript 會在您聲明name
的行上給您一個錯誤,因為它沒有預期的TextType
形狀。
另請注意,您應該將fields
聲明為Fields
類型,否則 TypeScript 無法理解這是預期的類型。
您的示例是一個很好的展示案例,為什么顯式類型注釋比類型斷言更受歡迎。
我期待打字稿會顯示一個錯誤,比如
Object name is missing validation
類型斷言會執行它們自己的兼容性檢查,因此您不會意外地將不兼容的類型(例如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',
},
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.