Typescript 替换对象键和值的泛型

Typescript replace generic for object keys and value

我有几个这样的代码块。有没有更好的方法来使用泛型或其他打字稿功能来做到这一点?

    const { authors } = book
    
    if (authors?.author) {
      if (Array.isArray(authors.author)) {
        book.authors = authors.author
      } else {
        book.authors = [authors.author]
      }
    }

    const { bookLinks } = book
    
    if (bookLinks?.bookLink) {
      if (Array.isArray(bookLinks.bookLink)) {
        book.bookLinks = bookLinks.bookLink
      } else {
        book.bookLinks = [bookLinks.bookLink]
      }
    }

我想创建一个带有两个参数的函数,比如 ('authors', 'author')('bookLinks', 'bookLink') 并替换上述代码中的变量。

我不是 100% 确定我遵循了用例,但也许您的函数可能如下所示:

function fixBook<K extends PropertyKey>(
    book: any, key: K, subKey: PropertyKey
): asserts book is { [P in K]?: unknown[] } {
    if (!book) throw new Error("This is not an object"); 
    const { [key]: prop } = book;
    if (prop?.[subKey]) {
        if (Array.isArray(prop[subKey])) {
            book[key] = prop[subKey];
        } else {
            book[key] = [prop[subKey]];
        }
    } 
}

这应该与您上面的代码类似。它是一个 assertion function,这意味着在你调用它之后,它会缩小输入对象的类型,以便你可以访问它的属性。

示例:

const book: unknown = {
    authors: { author: "A" },
    bookLinks: { bookLink: ["b", "c"] }
}

这里我们有 book 类型 unknown...带注释的 unknown 使编译器忘记了实际类型,所以这应该复制您得到 book 来自 API 并且不知道它是什么类型:

book.authors.author; // error! object is of type unknown

现在我们调用 fixBook() 两次。第一:

fixBook(book, "authors", "author");

在那句话之后,book 已经从 unknown 缩小到 {authors?: unknown[]}。 (请注意,它不是 {authors: string[]},因为编译器不知道 book?.authors?.author 是什么类型。按照不同的代码路径,我认为在 运行 函数之后,特定的 属性 将是 undefined 或一些未知类型的数组。)然后:

fixBook(book, "bookLinks", "bookLink");

在那句话之后,book 进一步缩小到 {authors?: unknown[]} & {bookLinks?: unknown[]}。我们可以通过访问 authorsbookLinks 属性来验证:

console.log(book.authors?.join(",")); // A
console.log(book.bookLinks?.join(",")); // b,c

看起来合理。


好的,希望对您有所帮助;祝你好运!

Playground link to code