我想撰寫一個靜態getOne<T>()類方法(即它不需要類實體或new運算子來使用它),它也是通用的,它回傳 MongoDB 物件作為ItemaBook或 a Film。這是我最初的想法,但現在我不知道如何動態使用'books'或'films'集合名稱字串來代替'xxx'.
import * as mongodb from 'mongodb';
const CONNECTION_STRING = 'MY_CONNECTION_STRING';
const BOOK_COLLECTION_NAME = 'books';
const FILM_COLLECTION_NAME = 'films';
interface Item {
_id: string
}
interface Book extends Item {
bookName: string,
description?: string
}
interface Film extends Item {
filmTitle: string,
duration?: number
}
function isBook(item: Item): item is Book {
return 'bookName' in item;
}
async function getOne<T extends Item>(): Promise<T | null> {
const client = new mongodb.MongoClient(CONNECTION_STRING);
await client.connect();
const db = client.db();
const collection = db.collection<T>('xxx');
// Instead of xxx I need to use BOOK_COLLECTION_NAME or FILM_COLLECTION_NAME
// depending on the actual type of T, how do I do that???
const item = await collection.findOne({});
if (item !== null) {
console.log(item._id);
if (isBook(item)) {
// Book type specific implementation
item.bookName = ' (best book ever)';
}
}
return item as T;
}
async function test() {
const book: Book | null = await getOne<Book>();
console.log(book?.bookName);
const film: Film | null = await getOne<Film>();
console.log(film?.filmTitle);
}
test();
這甚至可能嗎?我意識到我可以解決這個問題,將它作為引數傳遞給類似的東西await getOne<Book>('books'),但我想阻止這種情況(請參閱test()所需用法的函式)。
uj5u.com熱心網友回復:
這無法使用您想要的確切 API 來完成,因為您傳遞給函式的型別引數無法在運行時被函式訪問(以推斷表名)。您可以使用另一種方法,其中的名稱interface是從集合名稱中推斷出來的,因此傳遞'books'回傳Book | null、傳遞'films'回傳Film | null和傳遞其他任何內容都是編譯時錯誤。
type Collections = {
books: Book,
films: Film,
}
async function getOne<Name extends keyof Collections>(name: Name): Promise<Collections[Name] | null> {
// fetch the actual value here
return {} as Collections[Name];
}
async function test() {
const book: Book | null = await getOne('books');
console.log(book?.bookName);
const film: Film | null = await getOne('films');
console.log(film?.filmTitle);
// Argument of type '"comments"' is not assignable to parameter of type 'keyof Collections'.
await getOne('comments');
}
test();
操場
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/465681.html
