Reputation: 141
I am new to typescript and stuck in defining type of JSON object. In the following examples I want to define the type for myJSONObject
. The required types which I defined are JSONType_1
and 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
>;
}
As per this networkId
can either have group
key or individual
key.
When networkId
has group
key and who's value is = myFavGroup
, then I want this object to be type of JSONType_2
.
Notice the tasks
changes when group name is myFavGroup
.
Use case for above defined 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`.
}
}
Inside this if
condition I want myJSONObject
to have JSONType_2
and not JSONType_1 | JSONType_2
types.
As I want to send only JSONType_2
to a different function.
Error which I get:
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
is received from another service who's structures are fixed. 2 Examples:
{
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' },
];
}
Notice all tasks JSON objects are also predefined and fixed. The only difference is that tasks for myFavGroup
are different than any other group.
If there is a better way to code than what I am doing, I would appreciate your help in that too. Thanks in advance.
Upvotes: 0
Views: 1054
Reputation: 1359
Your code looks a bit dirty and I would consider some refactor, but!
// if group = 'myFavGroup' only for JSONType_2 you can exclude it for JSONType_1
interface NetworkIdOptions {
group?: Exclude<'myFavGroup', string>; // <---
individual?: string;
}
and
to make types compatible, you need to make group
property optional for JSONType_2
export interface JSONType_2 {
networkId: {
group?: 'myFavGroup'; // <---
};
}
This way after checking that networkId.group
is equal to 'myFavGroup' your Typescript compiler will automagically understand that your argument is of type JSONType_2
and you can successfully pass it to the differentFunction
Another solution would be just to use type assertion:
differentFunction(myJSONObject as JSONType_2)
Upvotes: 1