typescript - 如何避免`后续的属性声明必须具有与接口相同的类型`
问题描述
我有一些接口,它有一个枚举字段。还希望对此接口进行重载,这将在某些特定枚举值的情况下采用更多属性。
举个例子:
enum CellValueType {
DATE,
STRING,
NUMBER
}
export interface TableCell {
type: CellValueType;
value: string; // ...
}
export interface TableCell {
type: CellValueType.DATE;
format: string; // Should be exist only on the DATE type
value: string; // ...
}
但是,问题是使用界面时出现错误:
后续的属性声明必须具有相同的类型。属性“type”必须是“CellValueType”类型,但这里有“CellValueType.DATE”类型。
错误是可以理解的,没有问题。
主要问题是如何以合法的方式避免它。
我知道,我可以使用type
而不是interface
得到这个结构:
export type TableCell = {
type: CellValueType;
value: string;
} | {
type: CellValueType.DATE;
format: string;
value: string;
}
工作得很好,但问题是类不能实现联合类型。
无法按预期工作,DATE
但仍与第一个签名兼容。要正常工作,需要将type: CellValueType
其更改为type: Exclude<CellValueType, CellValueType.DATE>
此外,我可以仅为枚举类型创建一个子接口,DATE
但也希望避免为每种情况创建一个接口。
解决方案
当您以相同的名称定义两个接口时,将执行声明合并。
export interface TableCell {
type: CellValueType;
value: string; // ...
}
export interface TableCell {
type: CellValueType.DATE;
format: string; // Should be exist only on the DATE type
value: string; // ...
}
这是您在尝试CellValueType
与CellValueType.DATE
. 引用手册:
如果接口都声明了同名但类型不同的非函数成员,编译器将发出错误
现在,当您尝试使用联合来创建所需的类型时,您遇到了另一种设计行为 - 由于CellValueType.DATE
是 的成员CellValueType
,因此选择了更广泛的类型(想想看:A | ... | A | B
与 相同A | B
):
type isInType = CellValueType.DATE extends CellValueType ? true : false; //true;
type isNotInType = CellValueType extends CellValueType.DATE ? true : false; //false;
type cellType = TableCell["type"]; //CellValueType
既然如此,为什么不想创建扩展基本类型的接口呢?这是一个完全有效的抽象策略。看看下面的例子(注意as const
断言,否则类型CellValueType.DATE
将扩大到CellValueType
):
export enum CellValueType {
DATE,
STRING,
NUMBER
}
interface TableCell {
value: string;
}
export interface DateCell extends TableCell {
type: CellValueType.DATE;
format: string;
}
export interface NumberCell extends TableCell {
//number-specific props here
}
export class DateCell implements DateCell {
format = "yyyy-MM-dd";
type = CellValueType.DATE as const;
value = "2021-02-22";
}
推荐阅读
- node.js - NodeJs 与 Visual Studio 代码问题一起运行
- kubernetes - Kubernetes ClusterIP 服务是否可以从集群外部访问?
- r - 通过在 data.table 中处理的复杂组
- java - 嗨,我正在尝试学习 Selenium 自动化并收到此错误:无法初始化主类 org.testng.remote.RemoteTestNG
- java - 如何修复休眠未知实体异常?
- excel - 在 Excel VBA 中有没有办法编辑 MsgBox、vbYesNo 按钮标题?
- javascript - 更新所有对象值以四舍五入两位小数
- vue.js - 如何设置子组件 vuejs 的样式
- reactjs - React Router 6.0 在 nav/Link 中应用 basename 并且 nav/Link 在切换路由后消失
- javascript - 为什么我的 :leave-Animation 不起作用,尽管 :enter-animation 有效?