Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I filter an object by another鈥檚 values? #98

Closed
delucis opened this issue Mar 18, 2020 · 3 comments
Closed

How can I filter an object by another鈥檚 values? #98

delucis opened this issue Mar 18, 2020 · 3 comments
Labels
question More info is requested wiki It's nice to learn stuff

Comments

@delucis
Copy link

delucis commented Mar 18, 2020

馃 Question

Describe your question

Say we have an interface with some fields:

interface Data {
  x: string;
  y: string;
}

and a function that takes an object to select fields from that interface:

function select(opts: { x: boolean, y: boolean }) {
  const data: Data = getData() // from somewhere
  const o = {};
  for (const key in data) {
    if (opts[key] === true) o[key] = data[key];
  }
  return o;
}

How could we type the return such that it excludes fields in Data that are not true in the options object provided to select?

Thanks!

Search tags, topics

#typescript #object #filter #exclude

@millsp
Copy link
Owner

millsp commented Mar 18, 2020

It isn't possible so easily. Though it might be possible through writing you own custom type. First of all, start writing the type that will perform this:

interface Data {
    x: string;
    y: string;
}

type SelectIfTrue<O extends object, O1 extends object> =
    O.Pick<O, O.SelectKeys<O1, true>>

type t0 = SelectIfTrue<Data, {x: true, y: false}> // works

Then, you integrate the type to your function by casting its result:

// you will have to use `as const`. so we use a generic parameter
function select<O extends object>(opts: O) {
    const data: Data = {} as Data // from somewhere
    const o = {}

    for (const key in data)
        if (opts[key] === true) o[key] = data[key]

    return o as SelectIfTrue<Data, O> // casting the result
}

const t1 = select({x: true, y: false})			// not working
const t2 = select({x: true, y: false} as const) // works

I find this cumbersome. It is good to try to summarize TypeScript types. Even though this library can allow you to do such computations, you should not try to compute absolutely everything. Instead, your select should spit a simpler type out:

type t2 = O.Optional<Data>

@delucis
Copy link
Author

delucis commented Mar 18, 2020

@pirix-gh Thank you! Perhaps I should be less precise, it just seemed like it would be nice given the strict coupling between input and output. Thanks also for these great tools! 馃槂

@millsp millsp added question More info is requested wiki It's nice to learn stuff labels Mar 18, 2020
@millsp millsp closed this as completed Mar 18, 2020
@delucis
Copy link
Author

delucis commented Mar 18, 2020

Oh, although I notice that at least with the strict compiler option the as const assertion isn鈥檛 necessary, which was the main thing I disliked as it鈥檚 user-facing. Nice! Thanks again for your help.

Repository owner locked and limited conversation to collaborators Feb 2, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
question More info is requested wiki It's nice to learn stuff
Projects
None yet
Development

No branches or pull requests

2 participants