typescript - 是否可以有具有不同值类型的交集类型?
问题描述
我正在尝试编写可用于初始化模拟对象的初始化对象类型。我不想定义所有字段,因为我想重用这种类型。我定义了这样的自定义类型:
type InitObjType = { [key: string]: string } & { customKey?: Observable<boolean> };
function initializator(obj: InitObjType) {...}
如果我尝试将 init 对象传递给initializator
这样的函数:
const subject = new Subject<boolean>;
initializator({
a: 'a',
b: 'b',
c: 'c',
customKey: subject,
});
我收到错误:
error TS2345: Argument of type '{ a: string; b: string; c: string; customKey: Observable<boolean>; }' is not assignable to parameter of type 'InitObjType'.
Type '{ a: string; b: string; c: string; customKey: Observable<boolean>; }' is not assignable to type '{ [key: string]: string; }'.
Property 'customKey' is incompatible with index signature.
Type 'Observable<boolean>' is not assignable to type 'string'.
我使用 TypeScript 3.5.3。
有什么想法为什么类型的交集不起作用?
提前致谢!
解决方案
这里有一个关于索引类型的很好的解释。
声明索引签名基本上意味着所有显式属性也需要符合索引签名。在声明类型时,使用交集类型来解决此问题确实有效 - 但您将无法创建对象。github上也有一些关于这个的讨论。
使用子类型
将索引签名移动到这样的子类型被认为是最佳实践:
type InitObjType = {
customKey?: Observable<boolean>,
additionalProperties: { [key: string]: string }
};
function initializator(obj: InitObjType) {...}
const subject = new Subject<boolean>;
initializator({
customKey: subject,
additionalProperties: {
a: 'a',
b: 'b',
c: 'c',
}
});
使用较少的类型安全选项
如果您绝对必须将附加属性保持在同一级别,则必须使用类型安全性较低的方式。通过更改索引签名:
type InitObjType = {
customKey?: Observable<boolean>,
[key: string]: string | Observable<boolean>
};
// Or even less type-safe with any
type InitObjType = {
customKey?: Observable<boolean>,
[key: string]: any
};
或者在创建对象时进行类型转换:
const subject = new Subject<boolean>;
initializator({
a: 'a',
b: 'b',
c: 'c',
customKey: subject,
} as any);
最后一个例子有一个有趣的副作用。由于 TypeScript 只会阻止您创建这种类型的对象(因此您必须将其强制转换为任何类型),您仍然可以将该对象强制转换回来以再次获得类型安全(权衡是您必须每次都输入它)。
const subject = new Subject<boolean>;
initializator({
a: 'a',
b: 'b',
c: 'c',
customKey: subject,
} as any as InitObjType);
推荐阅读
- c - C中的类型转换查询
- machine-learning - 如何从经过训练的连续发射隐马尔可夫模型生成模拟数据
- javascript - 在节点模块中将 React 应用程序与 Parcel 捆绑在一起
- ruby-on-rails - 运行 rails g rspec 时出错:在 AWS cloud9 终端中安装
- javascript - 分页时数据表每页增加行数
- reactjs - 在 Axios 请求后,我的 React 状态仍然为空
- debugging - 如何调试 libcurl 以解决 IMAP 问题
- webpack - Gatsby:部署到 netlify 时“无法读取未定义的属性‘拆分’”
- python - (Python Numpy)如何从给定的 2D 数组创建新的 3D 数组?
- sql - 分区键的第一个键可以是集群键吗?