Export types for better TypeScript support.
I'm using this package in typescript. The searchAsync method returns a union type. I have to narrow it to a specific type to operate on the data. Otherwise, the typescript will continue to report an error, but since flexsearch does not export any type, this makes me unable to narrow its type, which further leads to me not being able to use flexsearch in strict typescript projects. So I hope to export all types, which helps the developer to take care of type safety by themselves, of course, it would be better if generic types that can provide more advanced conditional judgments.
Hi @flycran, I really would like to improve the generic return types. What I theoretically need is something like "conditional types" but I didn't know how to define them. I very much appreciate if you can help me to get into the right direction.
The result of the method Index.searchAsync is probably a good start. When option resolve: false was passed when calling this method, an instance of Resolver is returned. When leaving this option or passing resolve: true the type DefaultSearchResults is returned which resolves into Id[]. So there is some conditional type of result involved, based on passed parameter/nested options.
When I have some basic concept I can adopt this to all types accordingly. The solution should be extendable to multiple conditional parameters in different combinations later on to keep type definitions clean.
PR Great 🙌
@flycran We can continue discussion here. Would be nice if we can do the changes step by step. Probably best is to simplify types accordingly to your suggestion. Then we can do the types for Resolver afterwards.
As long I didn't missed anything, these are the steps:
- When
dbproperty was used by index creation (both: Index/Document), then the.search()method of this index type should be signed as deprecated along a deprecation message notify using.searchAsync()instead - When
workerproperty was used by document index creation, then the.search()method should be signed as deprecated along a deprecation message notify using.searchAsync()instead - Index.search and Document.search does not return Promises
If deprecation isn't possible then we should just apply the changes and I will add some jsdoc comments to the index.d.ts to provide some help.
What do you think?
@ts-thomas 这个提议非常好。
现在search已经按照预期工作了,在正式移除search的异步支持之前,可以先暂时保留目前对search的类型推断,在移除之后再简化类型也不迟。
另外我发现在v0.8.160新添加的类型还有一些问题,我稍候会看一下它是否正常工作
所以现在的步骤是
- 标记
.mount为已弃用 - 在使用了
dborworker的情况下对search调用发出警告,并建议改用searchAsync - 继续完成
Resolver的类型推断和v0.8.160新添加的类型
@flycran I've added some more generic properties like pluck and highlight and I also started with resolve (not completed yet).
Would be nice if you can take a look into this.
Really nice hint using @ts-expect-error flag for testing 🙌. I would like to add every combintation to "test/types.ts", so we have something we can check against.
@ts-thomas 如果你想将类型测试添加进CI,可以在测试流程中添加一条命令:
tsc --noEmit --lib esnext ./test/types.ts
这将在类型检查失败时中断CI tsc命令需要安装typescript
npm i typescript -D
@flycran I've added some test scenarios and have some questions.
- Accordingly to this message I would like to understand why types needs to be exported by index.d.ts and how do I know which of them should be selected to be exported?
- When compiling I got the error
node_modules/flexsearch/index.d.ts:906:13 - error TS2304: Cannot find name 'IDBDatabase'. - I've tested to add
--strictto the compiler flags and got some more issues likenode_modules/flexsearch/index.d.ts:157:38 - error TS2344: Type 'undefined' does not satisfy the constraint 'StorageInterface'. S extends StorageInterface = undefined,
Thanks in advance
@ts-thomas
- 经常被导出的类型包括用户用的到的类,类似
options这样复杂的参数类型,复杂方法的返回值类型,和一些用户可能用的到的工具泛型。 - 这是我在前面提到过的,新添加的类型定义不符合ts语法。
declare module的具体行为我也不清楚,我没有使用过它,可能是已经不推荐使用的老的语法,或许我可以尝试移除它。用我更熟悉的方法。 --strict会添加一些风格规范的检查,这些检查通常不会其他影响开发者使用你的包。使用typescript语言开发的项目通常默认开启。我在这里暂时没有使用strict,因为我觉得现在它不是很重要。
@flycran I've updated the index.d.ts and the test file It feels a bit messy, probably it could be simplified.
I have some issues within the test/types.ts file:
- https://github.com/nextapps-de/flexsearch/blob/master/test/types.ts#L125 when the property
customwas set the correspondingfieldproperty (one line above) should be any string and must not inherit fromDocumentData - https://github.com/nextapps-de/flexsearch/blob/master/test/types.ts#L175 There is some issue when I pass
indexorfieldto a Resolver Constructor also when I passindexorfieldin any of the and/or/not/xor methods - https://github.com/nextapps-de/flexsearch/blob/master/test/types.ts#L176 Calling
.resolve()of a document initialized resolver should returnDefaultDocumentSearchResultsinstead ofDefaultSearchResults
Would be nice if you can help me.
@ts-thomas 我在 #502 修复了第一条问题 原代码不工作的原因是泛型推断依赖于方法进行,如果没有通过泛型方法来推断,泛型参数将始终为默认值
@flycran nice 👍, I've also played around with your latest change to get a better understanding. This was really helpful to me. I've added some more example in line 179 to line 193 (test/types.ts ). I think this is the same issue here, the template type D extends DocumentData = undefined defaults to undefined but it should have DocumentData delegated.
There are two situations where a Resolver inherits from a Document or from Index.
One is actually working fine for both index types:
const index = new Index();
const document = new Document();
const indexResolver = index.search({ resolve: false });
const documentResolver = document.search({ resolve: false });
When passing index on a resolver method it does not properly inherit the index type:
const index = new Index();
const document = new Document();
// ok:
let indexResolver = new Resolver({ index: index });
// ok:
indexResolver = indexResolver.and({ index: index });
// issue:
let documentResolver = new Resolver({ index: document });
// issue:
documentResolver = documentResolver.and({ index: document, field: "title" });
Another issue was solved when fully type the result like here: https://github.com/nextapps-de/flexsearch/blob/master/test/types.ts#L50
Resolver<undefined, false, IndexedDB> = new Resolver({ index: index3 });
// index3 is a persistent index
But this fails:
Resolver = new Resolver({ index: index3 });
So it looks like the same issue as you mentioned with the property custom. As far I understand it needs a new type like StorageResolver right? Or should we define S extends StorageInterface | boolean = false to something else?
@flycran I was able to resolve all issues of the test file. Resolver type definitions looks almost completed.
@ts-thomas 那太好了,我之后会看看还有什么问题,最近我在忙自己的项目