我有一个Meta & Tag类型,如下所示:
export type Meta = {
title: string
date: Date
tags: Tag[]
slug: string // uses folder name as a slug
lastmod?: Date
draft?: Boolean
description?: string
image?: string
authors: string[]
readingTime: string
}
export type Tag =
| 'html'
| 'css'
| 'javascript'
| 'typescript'
| 'localstorage'
| 'reactjs'
| 'next.js'
| 'mdx'
| 'tailwindcss'
| 'mobx'
| 'nodejs'
| 'prisma'
| 'databases'
| 'postgresql'
| 'sqlite'
| 'windows'
| 'linux'
| 'mac'
| 'browser-extensions'
| 'dark-mode'我有一个getTagsByPost函数,它看起来像:
const getTagsByPost = (posts: Pick<Meta, 'title' | 'slug' | 'tags'>[]) => {
let allTags: Record<Tag, {title: string, slug: string}[]> | {} = {}
for (let { title, slug, tags } of posts) {
for (let tag of tags) {
const formattedTag = tag as Tag
const temp = { title, slug }
if (formattedTag in allTags) {
allTags[formattedTag].push(temp)
} else {
allTags[formattedTag] = [temp]
}
}
}
return allTags
}我在allTags[formattedTag]和if & else中都有一个错误。
if和else中的错误是:
元素隐式具有“任意”类型,因为类型'Tag‘的表达式不能用于索引类型'{}’。类型'{}'.ts(7053)上不存在属性'html‘
我希望函数返回如下所示的对象:
{
'mobx': [{
title: '',
slug: ''
}]
}我该怎么解决呢?
可再生TS游乐场可用这里。
发布于 2021-09-08 14:05:04
{}类型表示一个空对象;它不能拥有自己的任何属性,但可以访问全局Object上的属性。如果您查看一个空对象的字面示例,这是有意义的:
const empty = {};
empty.name // doesn't exist
empty.toString() // ok因此,allTags联合类型的Record<...> | {}包含一个空对象,不能分配它自己的任何属性。
这里可以这样断言一种更安全的编译类型:
const getTagsByPost = (posts: Pick<Meta, 'title' | 'slug' | 'tags'>[]) => {
let allTags = {} as Record<Tag, {title: string, slug: string}[] | undefined>;
for (let { title, slug, tags } of posts) {
for (let tag of tags) {
const formattedTag = tag as Tag;
const target = allTags[formattedTag];
const temp = { title, slug };
if (target) {
target.push(temp);
} else {
allTags[formattedTag] = [temp];
}
}
}
return allTags;
}我们知道我们将得到一个带有Tag键的对象,但是我们不能保证任何特定的键都会被填充。通过将动态对象属性赋值给变量,我们可以将undefined缩小到if块范围之外。有关为什么需要undefined类型的解释,请参见undefined。
发布于 2021-09-08 14:03:29
试试这个:
const getTagsByPost = (posts: Pick<Meta, 'title' | 'slug' | 'tags'>[]) => {
let allTags: Record<Tag, {title: string, slug: string}[]> = {} as Record<Tag, {title: string, slug: string}[]>
for (let { title, slug, tags } of posts) {
for (let tag of tags) {
const formattedTag = kebabCase(tag) as Tag
const temp = { title, slug }
if (formattedTag in allTags) {
allTags[formattedTag].push(temp)
} else {
allTags[formattedTag] = [temp]
}
}
}
return allTags
}对象字面语法{}引用类型' object‘。
当您用包含allTags的联合类型声明{}并使用对象文本初始化它时,allTags变量现在是object类型,因此在编写allTags[formattedTag]时它不能有Tag类型的键。
如果您想用Record<Tag, {title: string, slug: string}[]>类型初始化一个空对象,那么使用关键字as进行强制转换就可以了。
https://stackoverflow.com/questions/69104338
复制相似问题