【问题标题】:Typescript how to infer type from a constant property value打字稿如何从常量属性值推断类型
【发布时间】:2021-03-20 19:48:51
【问题描述】:

我想从之前定义的常量中获取属性的类型。

const my_constant = {
    user: {
        props: {
            name: {
                type: 'string'
            }
        }
    },
    media: {
        props: {
            id: {
                type: 'number'
            }
        }
    }
} as const;

type Name = keyof typeof my_constant;

type Constructed<T extends Name> = {
    [K in keyof typeof my_constant[T]['props']]: typeof my_constant[T]['props'][K]['type']

                                     // ~~~ Type '"type"' cannot be used to index type ...
}

我不明白为什么我不能使用“type”作为索引,但我可以使用“props”。

如果 typescript 可以推断出始终存在“props”属性,为什么它不能推断出始终存在“type”?

还有其他方法可以获取类型吗?

我想要实现的是这样的:


const user:Constructed<'user'> = {
    name: 'John'
}

const media:Constructed<'media'> = {
    id: 123
}

const user2:Constructed<'user'> = {
    name: 444
    // ~~~ Error
}

const media2:Constructed<'media'> = {
    id: 'something'
    // ~~~ Error
}

这是带有确切错误的游乐场链接:

Playground Link

【问题讨论】:

  • 我不确定这是否真的可行。运行时不存在输入(在其中运行 const)。
  • 如果您点击操场链接,您可以看到我可以轻松拥有“用户”和“媒体”类型,也可以使用“道具”对象类型。我不明白为什么我不能再往下一层。
  • 我还认为,您想要实现的是,该 id 具有打字稿类型“数字”。您正在分配一个类型文字。 playground

标签: typescript type-inference typescript-generics typeof


【解决方案1】:

Typescript 不能使用字符串来索引常量。它需要正确的密钥。 您可以检查对象是否具有属性type,也可以使用映射类型来获取真实类型,而不仅仅是“字符串”。

const my_constant = {
    user: {
        props: {
            name: {
                type: 'string'
            }
        }
    },
    media: {
        props: {
            id: {
                type: 'number'
            }
        }
    }
} as const;

type Name = keyof typeof my_constant;

type InferType<T> = T extends {type: infer I} ? I : never;

interface Mapped {
    string: string;
    number: number;
}

type Constructed<T extends Name> = {
    [K in keyof typeof my_constant[T]['props']]: 
        InferType<typeof my_constant[T]['props'][K]> extends keyof Mapped ?
            Mapped[InferType<typeof my_constant[T]['props'][K]>] : never
}

Playground Link

【讨论】:

    猜你喜欢
    • 2021-09-29
    • 2020-03-28
    • 2018-11-02
    • 1970-01-01
    • 1970-01-01
    • 2018-06-09
    • 2020-04-02
    • 2020-12-20
    • 2016-08-03
    相关资源
    最近更新 更多