首页 > 解决方案 > 打字稿如何从常量属性值推断类型

问题描述

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

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 ...
}

我不明白为什么我不能使用“类型”作为索引,但我可以使用“道具”。

如果打字稿可以推断出始终存在“道具”属性,为什么它不能推断出始终存在“类型”?

还有另一种方法可以获取类型吗?

我想要实现的是这样的:


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
}

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

游乐场链接

标签: typescripttype-inferencetypescript-genericstypeof

解决方案


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

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
}

游乐场链接


推荐阅读