首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >元素隐式具有“任意”类型,因为类型'Tag‘的表达式不能用于索引类型'{}’。类型'{}‘上不存在属性'html’

元素隐式具有“任意”类型,因为类型'Tag‘的表达式不能用于索引类型'{}’。类型'{}‘上不存在属性'html’
EN

Stack Overflow用户
提问于 2021-09-08 13:50:04
回答 2查看 190关注 0票数 2

我有一个Meta & Tag类型,如下所示:

代码语言:javascript
复制
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函数,它看起来像:

代码语言:javascript
复制
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中都有一个错误。

ifelse中的错误是:

元素隐式具有“任意”类型,因为类型'Tag‘的表达式不能用于索引类型'{}’。类型'{}'.ts(7053)上不存在属性'html‘

我希望函数返回如下所示的对象:

代码语言:javascript
复制
{
        'mobx': [{
            title: '',
            slug: ''
        }]
}

我该怎么解决呢?

可再生TS游乐场可用这里

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-09-08 14:05:04

{}类型表示一个空对象;它不能拥有自己的任何属性,但可以访问全局Object上的属性。如果您查看一个空对象的字面示例,这是有意义的:

代码语言:javascript
复制
const empty = {};
empty.name // doesn't exist
empty.toString() // ok

因此,allTags联合类型的Record<...> | {}包含一个空对象,不能分配它自己的任何属性。

这里可以这样断言一种更安全的编译类型:

代码语言:javascript
复制
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

票数 1
EN

Stack Overflow用户

发布于 2021-09-08 14:03:29

试试这个:

代码语言:javascript
复制
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进行强制转换就可以了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69104338

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档