我是TypeScript的新手,一直在寻找答案,但我很难找到我想要的东西。我看过Generic Constraints
,但我认为它不太正确。
所以如果我有一个Form
的接口,看起来像这样:
interface MyFirstForm {
myField: {
value: string;
valid: boolean;
myFirstArbitraryField: string
}
}
然后我想像这样定义另一个Form
:
interface MyOtherForm {
myField: {
value: string;
valid: boolean;
someOtherArbitraryField: number
}
}
很明显,value
和valid
对于这两个是常见的,所以我可能应该以某种方式提取它们。
在TypeScript文档中,他们说当你知道某个东西的形状但不知道它的值会被调用时,可以使用“索引签名”。那么在这种情况下,我们可以使用一个带有Index signature
的接口,并以任意形式扩展它吗?
类似这样的工作:
// The common values
interface FormField {
value: string;
valid: boolean;
}
// The common shape that we decide all our forms must conform to.
// Record<string, any> because we want to allow for extending the field objects
interface Form {
[key: string]: FormField & Record<string, any>;
}
// We define our Record from the Form interface so we do not loose type safety
interface ArbitraryForm extends Form {
myField: {
value: string;
valid: boolean;
arbitraryField: number
} // & FormField would also be valid
}
然而,通常当我扩展一个接口时,我不必指定我正在扩展的接口的值。在这种情况下,如果我从ArbitraryForm
属性中省略value
或valid
字段,我将得到一个类型错误。
我想要实现的是一种扩展接口的“形状”的方法,这样我就知道每当我在应用程序中创建表单时,我都应该扩展我的Form
接口,并且我将拥有最不可行的表单。
像这样(尽管这会导致类型错误):
interface FormField {
value: string;
valid: boolean;
}
interface Form {
[key: string]: FormField & Record<string, any>;
}
interface ArbitraryForm extends Form {
myField: {
arbitraryField: number
}
}
例如,如果我有一个检查有效性的函数,我就可以这样做
function isFormValid(form: Form): boolean {
return Object.values(form).every((field) => field.valid);
}
感谢任何答案或指针,我可以找到他们!
2条答案
按热度按时间rekjcdws1#
TypeScript中的对象类型已经是“开放的”或“可扩展的”,并且将允许额外的属性而不需要索引签名,并且由于将嵌套属性与索引签名相结合可能很棘手,让我们看看我们是否可以不这样做。
如果我们想要的只是将表单的每个属性与
FormField
合并,我们可以创建一个mapped type,通过交集来实现:同样,因为你可以有额外的属性,你的
isFormValid()
只需要指定属性的类型为FormField
,它就可以工作了:Playground链接到代码
g9icjywg2#
遗憾的是,使用这些接口,您无法扩展基本接口的属性,但是有一种替代解决方案,即使用
type
而不是interface
更新
更新以覆盖每个键,而不是整个对象