question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

FuseOptions<T> prevents nested key search

See original GitHub issue

Version: 3.3.0 Type: Potential Bug

Hi,

With the recent addition of typing to FuseOptions<T> and Fuse<T> nested key search is now giving Typescript compile errors.

The particular culprit is this line in the FuseOptions<T> interface

keys?: (keyof T)[] | { name: keyof T; weight: number }[];

An example of how this was used in my application:

  fuseOptions: FuseOptions<Template> = {
    shouldSort: true,
    threshold: 0.6,
    keys: [
      { name: 'metadata.title', weight: 0.8 },
      { name: 'metadata.category', weight: 0.1 },
      { name: 'metadata.summary', weight: 0.1 },
    ],
  };

Where metadata was a key in template and title is a key in metadata. This is no longer allowed by the interface. As a temporary solution I’ve included a // @ts-ignore above the fuseOptions definition and functionality is fully #restored.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:4
  • Comments:16 (12 by maintainers)

github_iconTop GitHub Comments

1reaction
favnacommented, May 24, 2019

@mmajko #309 and #310 have been created to cover deep nested keys. Furthermore https://github.com/piotrwitek/utility-types/issues/85 has been created to provide an even better solution, although that won’t be any near-future addition likely.

1reaction
ceymardcommented, Oct 25, 2018

Unfortunately such a thing is not possible. Typescript has no idea of how to handle path specifications since they’re completely implementation specific.

My best guess is that we should then go back to string instead of keyof T and forego the <T> in the type.

The sad thing about that is that you lose the robustness that comes with checking that the name indeed does exist.

I don’t know if the library supports it, but a good solution imho would be able to specify extractor functions. Not only would that probably be faster than parsing a path and resolving it, this would allow for some pretty strongly checked typing in typescript.

The implications is that a key could then be either specified by a string or a function.

This is the way that this could work ;


// An extractor is either a key for the object or an extracting function
// Here, I supposed the algorithm handles null or undefined
// values -- I suppose it does since path specifying can end up with non-existant properties
type Extractor<T> = keyof T | ((obj: T) => string | null | undefined)

// FuseOptions would become
interface FuseOptions<T> {
  // ... all the rest
  keys: Extractor<T>[] | { name: Extractor<T>; weight: number }[]
}

// By the way, I'm not clear on if we can mix simple keys with weighted ones.
// In this case, keys would be :
// (Extractor<T> | { name: Extractor<T>; weight: number })[]

  fuseOptions: FuseOptions<Template> = {
    shouldSort: true,
    threshold: 0.6,
    keys: [
      // This way, all the properties are properly checked. We are certain that they exist,
      // and if one day the code changes for the metadata object, this code will then
      // become an error, as it should.
      { name: t => t.metadata.title, weight: 0.8 },
      { name: t => t.metadata.category, weight: 0.1 },
      { name: t => t.metadata.summary, weight: 0.1 },
    ],
  };

  // Even better, when using the fuse constructor, you don't have to type everything explicitely
  var my_list = /* ... */ // my list gets a type thanks to the compiler inference

  // All the following is checked since typescript infers T from my_list's type.
  var fuse = new Fuse(my_list, {
    shouldSort: true,
    threshold: 0.6,
    keys: [
      { name: t => t.metadata.title, weight: 0.8 },
      { name: t => t.metadata.category, weight: 0.1 },
      { name: t => t.metadata.summary, weight: 0.1 },
    ],
  });

Read more comments on GitHub >

github_iconTop Results From Across the Web

javascript - Find by key deep in a nested array - Stack Overflow
Recursion is your friend. I updated the function to account for property arrays: function getObject(theObject) { var result = null; if(theObject instanceof ...
Read more >
Query nested objects in a document with unknown key
Hi,. I have a collection with many documents that do have a “item” property where the value is an object with key-value-pairs:
Read more >
Python Nested Dictionary (With Examples) - Programiz
Here, the nested_dict is a nested dictionary with the dictionary dictA and dictB . They are two dictionary each having own key and...
Read more >
Nested field type | Elasticsearch Guide [8.5] | Elastic
The nested type is a specialised version of the object data type that allows arrays of objects to be indexed in a way...
Read more >
JavaScript: how to find a key-value pair in a nested object.
How to recursively traverse a JavaScript nested and unordered object to find if a value exists at a specific key.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found