Closed Dante-101 closed 4 years ago
There is more:
with id
search(pattern: string): string[];
with includeMatches
search(pattern: string): { item: T; matches: any; }[];
with id
and includeMatches
search(pattern: string): { item: string; matches: any; }[];
its really ugly but modifying the definition file like this seems to work
export = Fuse;
export as namespace Fuse;
declare class Fuse<T, O extends Fuse.FuseOptions<T> = Fuse.FuseOptions<T>> {
constructor(list: ReadonlyArray<T>, options?: O)
search(pattern: string): O extends { id: keyof T } ?
O extends ({ includeMatches: true; } | { includeScore: true; }) ? Fuse.FuseResult<string>[] : string[] :
O extends ({ includeMatches: true; } | { includeScore: true; }) ? Fuse.FuseResult<T>[] : T[];
setCollection(list: ReadonlyArray<T>): ReadonlyArray<T>;
}
declare namespace Fuse {
export interface FuseResult<T> {
item: T,
matches?: any;
score?: number;
}
export interface FuseOptions<T> {
id?: keyof T;
caseSensitive?: boolean;
includeMatches?: boolean;
includeScore?: boolean;
shouldSort?: boolean;
sortFn?: (a: { score: number }, b: { score: number }) => number;
getFn?: (obj: any, path: string) => any;
keys?: (keyof T)[] | { name: keyof T; weight: number }[];
verbose?: boolean;
tokenize?: boolean;
tokenSeparator?: RegExp;
matchAllTokens?: boolean;
location?: number;
distance?: number;
threshold?: number;
maxPatternLength?: number;
minMatchCharLength?: number;
findAllMatches?: boolean;
}
}
@gatimus hats off to you. Your solution appears to be the correct one. I'd love it if you could PR the repo with that solution. (note: I'm not the maintainer. I just think you created some awesome types that would be really helpful for many people 🥇 👍 )
The type definition seems to have been updated with @william-lohan's suggestions but it's unclear how it's supposed to work. Could someone post an example?
Here's what I came up with:
interface User {
email: string;
}
const FUSE_OPTIONS: Fuse.FuseOptions<User> & { includeScore: true } = {
includeScore: true,
keys: ['email']
};
new Fuse<User, typeof FUSE_OPTIONS>([...]).search('query')
The & { includeScore: true }
part is weird but without that it considers includeScore
to be as Fuse.FuseOptions
defines it: boolean | undefined
. It doesn't seem to satisfy the O extends ({ includeMatches: true; } | { includeScore: true; })
as it doesn't return a Fuse.FuseResult<T>
but a T
.
@Zhouzi it errors on the side of optional properties being undefined (ie includeScore
in optional so according to the conditional return it is undefined unless explicitly shown as defined ex your & { includeScore: true }
). It works better if you let TypeScript infer the type from the object literal. See res1
below.
import * as Fuse from "fuse.js";
interface User {
email: string;
}
const src: User[] = [];
const res1: Fuse.FuseResult<User>[] = new Fuse(src, {
includeScore: true,
keys: ["email"]
}).search("query");
const res2: User[] = new Fuse(src, {
keys: ["email"]
}).search("query");
const emailKey: keyof User = "email";
const res3: Fuse.FuseResult<string>[] = new Fuse(src, {
id: emailKey,
includeScore: true,
keys: ["email"]
}).search("query");
const res4: string[] = new Fuse(src, {
id: emailKey,
keys: ["email"]
}).search("query");
I could make some improvement on the keyof User
"weirdness" in the last 2 examples but haven't came up with anything yet.
@william-lohan thank you! 👍 Following your example, I got it working like so:
interface User {
email: string;
}
const users: User[] = [
{
email: 'jane@doe.com'
},
{
email: 'john@doe.com'
}
];
const matchingUsers: User[] =
new Fuse(users, {
includeScore: true,
shouldSort: false,
keys: ['email']
})
.search('jane')
.map(result => result.item);
There are two important limitations: Fuse.FuseOptions
cannot be used and the options object has to be inlined. For example, the following doesn't work:
interface User {
email: string;
}
const users: User[] = [
{
email: 'jane@doe.com'
},
{
email: 'john@doe.com'
}
];
const FUSE_OPTIONS = {
includeScore: true,
shouldSort: false,
keys: ['email']
};
const matchingUsers: User[] =
new Fuse(users, FUSE_OPTIONS)
.search('jane')
.map(result => result.item);
Anyway, I believe the initial issue has been fixed and can be closed.
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days
Current TS definition says,
search(pattern: string): T[]
But with
includeScore
, the search returns:search(pattern: string): T[] | { item: T, score: number }[];
For now, I am ignoring the return type with
// @ts-ignore
.