我有几个看起来像这样的代码块。有没有更好的方法可以通过泛型或其他打字稿功能来做到这一点?
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')
)的函数并替换变量。
答案 0 :(得分:1)
我不确定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
使编译器忘记了实际的类型,因此这应该复制您得到{{1} },并且不知道它是什么类型:
book
现在,我们两次致电book.authors.author; // error! object is of type unknown
。首先:
fixBook()
在该语句之后,fixBook(book, "authors", "author");
的范围从book
缩小到unknown
。 (请注意,它不是{authors?: unknown[]}
,因为编译器不知道{authors: string[]}
是什么类型。按照不同的代码路径,我认为在运行函数后,特定属性要么是{{1 }}或一些未知类型的数组。)然后:
book?.authors?.author
该语句之后,undefined
的范围进一步缩小到fixBook(book, "bookLinks", "bookLink");
。我们可以通过访问book
和{authors?: unknown[]} & {bookLinks?: unknown[]}
属性进行验证:
authors
看起来很合理。
好的,希望能为您提供一些指导;祝你好运!