#Optional includes

17 messages · Page 1 of 1 (latest)

fading sundial
#

I'm trying to make an api wrapper. The api allows you to include related entities.
For example, if you want to fetch a server, you can also fetch its owner.

I want the library to be used like

const server = await api.servers.fetch("id");
server.relations.user // undefined (or null)

const server = await api.servers.fetch("id").includeUser();
server.relations.user; // User

I'm not advanced with typescript, so I'm not sure what's the best way to approach this.
I've gotten something to work, but it only works with one include. If you try to chain them, it will only use the latest one. I also have a @true ivy-ignore which I'm not sure how to remove.

I'm also okay with server.relations.get("user") if that can be typed.

ionic tartanBOT
#

@fading sundial Here's a shortened URL of your playground link! You can remove the full link from your message.

${j122j}#6974

Preview:```ts
// https://stackoverflow.com/a/49683575/9499862
type OptionalPropertyNames<T> =
{ [K in keyof T]-?: ({} extends { [P in K]: T[K] } ? K : never) }[keyof T];

type SpreadProperties<L, R, K extends keyof L & keyof R> =
{ [P in K]: L[P] | Exclude<R[P], undefined> };
...```

tender spoke
#

looks like some builder pattern

#

where you return the same object, adding properties to it every time

#

it should be relatively easy to do in TypeScript using generics

fading sundial
#

Yeah like a builder. Do you maybe have some example on how it's done? I've never worked with more complex stuff.

ionic tartanBOT
#
Ascor8522#7606

Preview:```ts
class Server {
getFoo<T extends Server>(
this: T
): T & {result: {foo: string}} {
return this as T & {result: {foo: string}}
}

getBar<T extends Server>(
this: T
): T & {result: {bar: string}} {
return this as T & {result: {bar: string
...```

tender spoke
#

it's not that complicated, but it involves a few tricks

#

you want to add new properties to the object that is returned by each method, and retain those

#

to do that, you need to take the current object the method was called on, and merge it (intersection) with a new object containing the added property

#

you need to take the current object the method was called on
to do that, you can specify this in your method, like so method(this)

#

it represents the object the method is called on

fading sundial
#

OH, I had something like this at first. But I used | instead of &. Haven't coded in typescript in a while, totally forgot how it worked.

tender spoke
#

now, since the final object is the same as the this you got, you need to use generics to tell TS the type is the same

tender spoke
fading sundial
#

Thanks, this really helped especially with generics part.

#

!resolved