PouchDB の間違った (?) TypeScript/DefinitelyTyped 型定義を回避する方法は?
私はTypeScriptとPouchDBの型宣言についての助けを探しています。次のTSコードを考えてみてください:
import PouchDB = require('pouchdb')
import find = require('pouchdb-find')
PouchDB.plugin(find)
const data = new PouchDB("http://localhost:5984/data"),
export async function deleteLastRevForIds(dbname, ids) {
const docsToDelete = await data.find({
fields: ["_id", "_rev"],
selector: { _id: { $in: ids } }
})
const deletePromise = docsToDelete.docs.map(doc => {
return data.remove(doc) // <-- HERE TSC SHOUTS AT ME about `doc`
})
const deletion = await Promise.all(deletePromise)
return deletion
}
注釈付きの remove() 呼び出しで、tsc はこのエラーを出力します:
Argument of type 'IdMeta' is not assignable to parameter of type 'RemoveDocument'.
Type 'IdMeta' is not assignable to type 'RevisionIdMeta'.
Property '_rev' is missing in type 'IdMeta'.'
起こっていることは、find() の呼び出しが DefinitelyTyped の型定義によって {docs: PouchDB.Core.IdMeta[]} を返す型として指定されているということです。そしてその名前が示す通り、PouchDB.Core.IdMeta[] は {_id: string} の配列を意味します。
でもそれは間違いです!PouchDB.find()は単に{_id: ...}オブジェクトのリストを返すわけではなく、{_id: ..., _rev: ...}のリストを返します(しかも私は明示的にこの2つのフィールドを要求しました)。それとも何か見落としているのでしょうか?
その結果、このようなオブジェクトを使って remove() 関数(DT の型定義によって、完全に指定された _id+_rev RevisionIdMeta を必要とするように正しく型付けされている)を呼び出すと、TS は正しく警告を出します。
私はこの物をあらゆる方向にキャストしようとしましたが、自分の思い通りには曲げられませんでした;tscは、私のオブジェクトから_revが欠けているとエラーを出し続けます。
- 私がそのような「深い」キャストをする方法はありますか?
- もしそうでない場合、DTの型定義をできるだけローカルで上書きする方法はありますか?
- 私は全く別のことをすべきでしょうか?
それと、DTの型定義に変更を提案すべきでしょうか?
ありがとう。
回答 #1
そう、Pouchdb-find の定義は間違っています。これに似たものがあれば、動き始めるはずです…
const data = new PouchDB("http://localhost:5984/data")
interface FixedFindResponse<Content extends PouchDB.Core.Encodable> {
docs: PouchDB.Core.ExistingDocument<Content>[];
}
export async function deleteLastRevForIds(dbname: void, ids: number[]) {
const docsToDelete: FixedFindResponse<any> = await data.find({
fields: ["_id", "_rev"],
selector: { _id: { $in: ids } }
})
const deletePromise = docsToDelete.docs.map(doc => {
return data.remove(doc) // <-- HERE TSC SHOUTS AT ME about `doc`
})
const deletion = await Promise.all(deletePromise)
return deletion
}回答 #2
私がそのような「深い」キャストをする方法はありますか?
常に as any as Whatever を使って何かを再キャストすることができます。明らかに、型が正しく取得できない場合の最後の手段として使うべきであり、このアサーションにはまったく安全性がありません。例えば 123 as any as Window はコンパイルされます。
DTの型定義をできるだけローカルに上書きする方法はありますか?
はい、宣言のマージ: モジュールの拡張を見てください。
私は全く別のことをすべきでしょうか?
型定義が間違っていると確信している場合は、それを修正してDefinitelyTypedにPRを提出することもできます。
