#Combining parts of objects in TypeScript
1 messages · Page 1 of 1 (latest)
You can use the Pick<> and Omit<> utility types to get what you need. https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys
Types which are globally included in TypeScript
Then you can combine what you get.
Here's how it would look, and note that I'm guessing on the shape of your types.
type PlayerBio = {
id: string;
name: string;
team: string;
}
// Note how playerId is used here and would reference a PlayerBio
type PlayerStats = {
id: string;
playerId: string;
wins: number;
losses: number;
draws: number;
}
// This takes the PlayerBio type and joins it with the modified PlayerStats type.
// The Omit utility strips out the types that aren't needed in both places
// In this case, 'id' would be duplicated and 'playerId' is not needed
type PlayerDetail = PlayerBio & Omit<PlayerStats, "id" | "playerId">;
// This object has all properties of the PlayerDetail type
const player: PlayerDetail = {
id: "abc123",
name: "Joe Player",
team: "Joe's Team",
wins: 4,
losses: 2,
draws: 0
}
This makes sense for the most part. How do I parse this into JSON? I feel like I'm missing a step to get it to output all the playerDetails
I may be asking the question wrong, or not understanding. I have an index.ts file that contains the following two types
fullName: string;
shortName: string;
position: string;
playerId: number;
imgId: number;
orgId: number;
orgAbbr: string;
teamAbbr: string;
};
export type PlayerStatsDTO = {
playerId: number;
serviceTime: number;
g: number;
gs: number;
ip: number;
h: number;
hr: number;
bb: number;
k: number;
np: number;
era: number;
fip: number;
hPer9: number;
hrPer9: number;
bbPer9: number;
kPer9: number;
walkRate: number;
kRate: number;
gbRate: number;
};```
From there I have a `playerStats.ts` and a `playerBios.ts` files that have similar text to the following
```import { PlayerBioDTO } from "../types";
export const playerBios: PlayerBioDTO[] = [
{
fullName: "Burke, Trevor",
shortName: "Burke T.",
position: "RHS",
playerId: 123456,
imgId: 621057,
orgId: 1,
orgAbbr: "TBD",
teamAbbr: "TBD",
},```
I want to create a `PlayerDetailDTO` type (which I think I accomplished with the above `Omit`. What I'm missing is pulling the data from the `playerStats.ts` and `playerBios.ts` to create the `playerDetails.ts` file. If I do a spread operator to try and combine, it just console logs the bio and stats separately. Thoughts?
OK, so there's a couple things at play here. First, keep in mind that Typescript is only checking things at compile time, so you will need to do a runtime transform to get the actual data into the proper shape. (which I think you are trying to do) That said, you can address the typescript shapes first. The example I have used Omit<T, keys> but you can use Pick<T, keys> if you have less keys you want to keep than the keys you want to omit. Then in the line type PlayerDetail = PlayerBio & Omit<PlayerStats, "id" | "playerId">;, the & symbol merges the two types into one. That gives you your final shape.
By trying to use the spread operator you are trying to put all the keys from both objects into it, and Typescript should yell at you for that. You can work around that in a couple of ways.
- You destructure the keys you need from your runtime JS from each type, then apply them to the
Detailobject. This is the simplest in theory but also requires you to manually maintain it with less assistance from typescript.
const { fullName, shortName, playerId } = someBioDtoObject;
const { serviceTime, g, gs } = someStatsDtoObject;
const detailDto: PlayerDetailDTO = {
fullName,
shortName,
playerId,
serviceTime,
g,
gs,
}
You can see that gets unwieldy though, so there is another option if you want to jump a bit farther down the rabbit hole.
- The way I would do this, given the shape of the objects you gave me, is to make use of Zod and a small utility for it called toZod.
https://www.npmjs.com/package/zod
https://www.npmjs.com/package/tozod
Zod will allow you to build validators that will take what you put in to them, and strip out any keys it doesn't have a validator set up for. What toZod does is give you a way to leverage typescript to enforce that your zod validator matches a typescript type shape for it's output, thereby giving you a compile time check for compliance to a runtime shape.
Option 1 will totally work, and if your data shapes are static and stable it's probably the better option. You also don't need to fuss with another dependency, and learn it if you don't know it already.
OTOH option 2 will provide greater long term flexibility. If you change one thing feeding the types, Typescript will pick it up wherever it needs to change.
@errant galleon thanks for all the info. I'll definitely dive back into this in a little bit. I'm probably going to do option 1. Mostly because I'm learning TS as I do this and don't want to further melt my brain by adding onto that lol.
I totally get it. Did option 1 make sense?
It does, when reading. I'm sure in doing I'll get tripped up a little. But if I run into issues I will let you know.
I'm missing a step somewhere and I'm drawing a blank. I have my type and everything set up from option 1. But I'm having an issue getting it all to compile the player details together to put it in my playerDetails.ts file.
@pearl cedar Do you have this in a GH repo you can share? If so, push your latest changes and send me a link.
Also what specific error message are you getting?
It's in a codesandbox, would you be up for a call I can screenshare
got people in and out of my office like crazy 😂 call probably won't work. Share your related code here if that's OK, I'll be popping in and out.
haha I get it. I'll do so in a few
Actually if you are in a codesandbox you can do a liveshare with that. If you are OK with me looking things over between putting out fires we can try it. Should be a share button or something in the top bar iirc, I played with it a long time ago.