ウェブサイト検索

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を提出することもできます。