typescript - 打字稿将缺少的字段添加到应该具有它们的类型
问题描述
我正在尝试为我的数据库代码创建一个辅助函数。数据库中的每个表都有一些公共字段(pk、创建日期等),这些字段被实现为其他表的接口扩展的公共接口。我想创建一个函数,自动将这些公共属性添加到对象并返回新对象,但是打字稿以我无法理解的方式抱怨子类型分配......
Type '{ id: string; } & Pick<T, Exclude<keyof T, "id">>' is not assignable to type 'T'.
'{ id: string; } & Pick<T, Exclude<keyof T, "id">>' is assignable to the constraint of type
'T', but 'T' could be instantiated with a different subtype of constraint 'Common'
我在 TS 操场上做了一个最小的代码示例来重现它。对于给定类型,T 扩展了 Common 基接口,我想接受一个包含 T 的所有必需字段的对象,除了Common 中的那些,然后返回带有添加字段的对象。
interface Common {
id: string;
}
interface Table extends Common {
data: string;
}
function makeDbEntry<T extends Common>(initial: Omit<T, 'id'>): T {
const common: Common = {
id: 'random string',
};
const ret: T = {
...common,
...initial,
};
return ret;
}
据我所知,似乎没有任何方法可以在不明确列出其字段的情况下从 T 中删除字段(不能执行“T 减去 Common”)...
解决方案
如果条件类型包含类型参数,则无法完全解析它们。这意味着,至少对于这个用例来说,Omit<T, 'id'>
基本上是不透明的,TS 看不到这个类型是什么,它只是一个不同于T
.
Omit<T, 'id'>
当您进行展开操作时,TS 正确理解这将在 common 和( { id: string; } & Omit<T, 'id'>
)之间产生交集。但是因为Omit
正如我所说的那样不透明,所以无法对这种类型进行进一步的简化。尽管对人类来说这很容易解决T
,但 typescript 不知道如何简化这种类型。
如果替换T
为具体类型,则 ts 可以很容易地理解 example{ id: string; } & Omit<Table, 'id'>
与 相同Table
,因此可以使用:
function makeDbEntry<T extends Common>(initial: Omit<T, 'id'>): T {
const common: Common = {
id: 'random string',
};
const ret: T = {
...common,
...initial,
} as T;
return ret;
}
对于通用版本,最好的选择是使用类型断言,因为在大多数情况下,开发人员比编译器有更好的理解:
function makeDbEntryForTable(initial: Omit<Table, 'id'>): Table {
const common: Common = {
id: 'random string',
};
const ret: Table = {
...common,
...initial,
};
return ret;
}
推荐阅读
- vba - VBA 搜索没有 msgBox 但使用用户窗体代替
- javascript - AWS Lambda 无法导入模块“索引”:错误
- android - 如何访问操作系统级别的时间格式设置 ion React Native
- javascript - p5.speechrec 不适用于 chrome 弹出窗口和背景
- python - 如何在django中将来自同一模型的两个不同排序的查询集一个接一个地合并在一起
- python-3.x - For循环中的kivy按钮事件
- android - 将质数保存到文件
- bigcommerce - 通过 API 获取字段选项
- php - 将 2 个日期之间的天数插入数据库
- python - Audiosegment 对象和波形文件/数据之间的转换