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[]}
。我们可以通过访问 authors
和 bookLinks
属性来验证:
console.log(book.authors?.join(",")); // A
console.log(book.bookLinks?.join(",")); // b,c
看起来合理。
好的,希望对您有所帮助;祝你好运!
我有几个这样的代码块。有没有更好的方法来使用泛型或其他打字稿功能来做到这一点?
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[]}
。我们可以通过访问 authors
和 bookLinks
属性来验证:
console.log(book.authors?.join(",")); // A
console.log(book.bookLinks?.join(",")); // b,c
看起来合理。
好的,希望对您有所帮助;祝你好运!