typescript - 获取 TypeScript 联合字段的类型
问题描述
我有一个看起来像这样的联合类型:
type Option1 = {
items: string[];
}
type Option2 = {
delete: true;
}
type Combined = Option1 | Option2;
我想用items
字段的类型定义一个新变量:
const items_variable:Combined["items"] = ["a", "b"];
但这给了我错误error TS2339: Property 'items' does not exist on type 'Combined'
。
如果我使用的是值而不是类型(我所看到的所有现有答案都假设),我可以在这里使用类型缩小,但是我不明白如何在现有类型上做到这一点。
Option2
如果定义它似乎也可以按预期工作,items
但这对我的用例没有意义。
我应该使用什么类型items_variable
?
解决方案
这就是 TS 工会的工作方式。这是设计使然。
type Option1 = {
items: string[];
}
type Option2 = {
delete: true;
}
type Combined = Option1 | Option2;
type Keys = keyof Combined; // never
如您所见,keyof Combined
返回never
- 空键集。
因为Option1
andOption2
没有任何共同的 props,所以 TS 不确定允许什么属性。
假设您有一个期望Option1
or的函数Option2
。为了以Combined
安全的方式使用,您应该使用自定义类型保护:
type Option1 = {
items: string[];
}
type Option2 = {
delete: true;
}
type Combined = Option1 | Option2;
type Keys = keyof Combined; // never
const hasProperty = <Obj, Prop extends string>(obj: Obj, prop: Prop)
: obj is Obj & Record<Prop, unknown> =>
Object.prototype.hasOwnProperty.call(obj, prop);
const handle = (union: Combined) => {
if (hasProperty(union, 'items')) {
const option = union; // Option1
} else {
const option = union; // Option2
}
}
或者您可以添加公共属性:
type Option1 = {
tag: '1',
items: string[];
}
type Option2 = {
tag: '2',
delete: true;
}
type Combined = Option1 | Option2;
type CommonProperty = Combined['tag'] // "1" | "2"
const handle = (union: Combined) => {
if(union.tag==='1'){
const option = union // Option1
}
}
另一种替代方法是使用StrictUnion
.
type Option1 = {
items: string[];
}
type Option2 = {
delete: true;
}
type Combined = Option1 | Option2;
// credits goes https://stackoverflow.com/questions/65805600/type-union-not-checking-for-excess-properties#answer-65805753
type UnionKeys<T> = T extends T ? keyof T : never;
type StrictUnionHelper<T, TAll> =
T extends any
? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, never>> : never;
type StrictUnion<T> = StrictUnionHelper<T, T>
type Union = StrictUnion<Combined>
const items_variable: Union['items'] = ["a", "b"]; // string[] | undefined
您可能已经注意到,有一个小缺点,items_variable
可能也是undefined
. 这是因为工会的性质。它可以是一个值,也可以是另一个值。
推荐阅读
- mysql - 根据 LIKE 运算符从一个表中删除到另一个表
- python - 在 Pandas 中排列借方和贷方?
- optimization - 优化 google api 请求以从 youtube 视频中检索数据
- python - 合并两个只有一列不同的数据框。需要将该列附加到新数据框中。请查看下面的详细视图
- ssl - 在 nginx 中使用 LetsEncrypt 将非 http 链接重定向到 HTTPS 链接
- nativescript - 迁移到 NativeScript 7
- python - 有人告诉我,python 线程并不意味着我的代码是并行运行的,但确实如此。有人可以解释吗?
- r-markdown - 为什么 blogdown::hugo_build() 不能处理 Lua 过滤器?
- laravel - 如何从嵌套关系中获取特定列 - Laravel
- git - 如何根据我要克隆的 git 存储库来源自动更改我的本地 git config `user.email`?