打字稿如何定义对象,其中键的值取决于另一个键
Posted
技术标签:
【中文标题】打字稿如何定义对象,其中键的值取决于另一个键【英文标题】:Typescript how to define object in which key's value depends on another key 【发布时间】:2021-01-30 15:46:14 【问题描述】:我是 typescript 的新手,一直在定义 JSON 对象的类型。在以下示例中,我想为myJSONObject
定义类型。我定义的所需类型是JSONType_1
和JSONType_2
。
type RequireOnlyOne<T, Keys extends keyof T = keyof T> =
Pick<T, Exclude<keyof T, Keys>>
&
[K in Keys]-?: Required<Pick<T, K>> & Partial<Record<Exclude<Keys, K>, undefined>>
[Keys];
interface NetworkIdOptions
group?: string;
individual?: string;
type NetworkId = RequireOnlyOne<NetworkIdOptions, 'group' | 'individual'>;
export interface JSONType_1
networkId: NetworkId;
tasks: Array<
| taskInterface_1
| taskInterface_2
| taskInterface_3
>;
export interface JSONType_2
networkId:
group: 'myFavGroup';
;
tasks: Array<
| taskInterface_4
| taskInterface_5
>;
根据这个networkId
可以有group
密钥或individual
密钥。
当networkId
有group
键并且谁的值是=myFavGroup
时,我希望这个对象是JSONType_2
的类型。
请注意,当组名称为 myFavGroup
时,tasks
会发生变化。
上面定义的JSONType_1
& JSONType_2
的用例:
myFunc(myJSONObject: JSONType_1 | JSONType_2)
if (myJSONObject.networkId.group && myJSONObject.networkId.group === 'myFavGroup')
differentFunction(myJSONObject) // this function takes input only in `JSONType_2`.
在这个if
条件中,我希望myJSONObject
具有JSONType_2
而不是JSONType_1 | JSONType_2
类型。
因为我只想将JSONType_2
发送到不同的功能。
我得到的错误:
Argument of type 'JSONType_1 | JSONType_2' is not assignable to parameter of type 'JSONType_2'.
...
Types of property 'group' are incompatible.
Type 'string' is not assignable to type '"myFavGroup"'.
myJSONObject
来自另一个结构固定的服务。 2个例子:
networkId:
group: 'Desktop_group';
;
tasks: [
cmd: 'playMusic', songName: 'xyz' ,
cmd: 'playVideo', videoName: 'abc' ,
];
networkId:
group: 'myFavGroup';
;
tasks: [
cmd: 'sendMusicList', path: '/home/user/musicFolder' ,
cmd: 'sendFilesStats', path: '/home/user/someFolder' ,
];
请注意,所有任务 JSON 对象也是预定义和固定的。唯一的区别是myFavGroup
的任务不同于任何其他组。
如果有比我正在做的更好的编码方式,我也会感谢您的帮助。提前致谢。
【问题讨论】:
你如何声明 myJSONObject 或结构是什么?可以举个例子吗? 通过添加我收到的 myJSONObject 示例来编辑问题。 @MBB 【参考方案1】:您的代码看起来有点脏,我会考虑进行一些重构,但是!
// if group = 'myFavGroup' only for JSONType_2 you can exclude it for JSONType_1
interface NetworkIdOptions
group?: Exclude<'myFavGroup', string>; // <---
individual?: string;
和
要使类型兼容,您需要将group
属性设为JSONType_2
的可选属性
export interface JSONType_2
networkId:
group?: 'myFavGroup'; // <---
;
这样,在检查 networkId.group
等于 'myFavGroup' 之后,您的 Typescript 编译器会自动理解您的参数是 JSONType_2
类型,并且您可以成功地将其传递给 differentFunction
另一种解决方案就是使用类型断言:
differentFunction(myJSONObject as JSONType_2)
【讨论】:
谢谢 Dmitry,对不起这个脏代码,我还在学习打字稿。你想建议我怎样才能让它更干净吗?第一个解决方案也不起作用,它在Types of property 'tasks' are incompatible.
上引发错误,因为我们可以看到myFavGroup
的任务不同。但第二个解决方案奏效了。以上是关于打字稿如何定义对象,其中键的值取决于另一个键的主要内容,如果未能解决你的问题,请参考以下文章