【问题标题】:TypeScript: Infer literal type of already defined typeTypeScript:推断已定义类型的文字类型
【发布时间】:2022-02-02 04:05:31
【问题描述】:

不确定这是否可能或最好的描述,但我需要推断已经由另一个类型/接口定义的类型的字面量类型。

例如,我有一个遵循某个接口的对象:

interface MyObject {
    foo: string | number;
    bar: string[];
}
const MY_OBJECT: MyObject = {
    foo: 123,
    bar: ["abc", "def"],
};

现在,我想知道 MY_OBJECT 的类型文字,通过执行以下操作:

type MyObjectLiteral = Infer<typeof MY_OBJECT>;

那应该是MyObjectLiteral: { foo: 123, bar: ["abc", "def"] }

问题是如何定义type Infer&lt;T&gt;来返回T的推断类型。

任何帮助或澄清将不胜感激。

【问题讨论】:

    标签: typescript generics type-inference


    【解决方案1】:

    仅靠类型是不可能的。一旦您将值分配给比推断范围更宽的类型,您就会丢失该类型信息。

    但您始终可以将更窄的类型视为包含它的更宽的类型。这意味着您可以随时选择其他方向。


    您可以简单地声明您的对象as const,然后在任何接受MyObject 类型的地方使用它。

    interface MyObject {
        foo: string | number;
        bar: readonly string[];
    }
    
    const myObject = { foo: 123, bar: ["abc", "def"] } as const
    const barZero = myObject.bar[0] // type: "abc"
    
    const myObjectWide: MyObject = myObject // works
    const barWideZero = myObjectWide.bar[0] // type: string
    

    Playground


    或者,如果您想限制 myObject 的构造,您可以使用函数来捕获确切的子类型,并将其返回。

    例如:

    interface MyObject {
        foo: string | number;
        bar: readonly string[];
    }
    
    function makeObj<T extends MyObject>(myObject: T): T {
        return myObject
    }
    
    const myBadObject = makeObj({ bad: true } as const)
    // Argument of type '{ readonly bad: true; }' is not assignable to parameter of type 'MyObject'.
    //  Object literal may only specify known properties, and 'bad' does not exist in type 'MyObject'.(2345)
    
    const myObject = makeObj({ foo: 123, bar: ["abc", "def"] } as const)
    const barZero = myObject.bar[0] // type: "abc"
    
    const myObjectWide: MyObject = myObject // works
    const barWideZero = myObjectWide.bar[0] // type: string
    

    Playground

    【讨论】:

    • 感谢您的详细解答!不幸的是,我仅限于我试图解决的泛型悖论的基于类型的解决方案,所以我想我现在必须考虑另一种解决方案。
    猜你喜欢
    • 2019-09-17
    • 2018-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-18
    • 2017-10-04
    • 2018-10-20
    • 1970-01-01
    相关资源
    最近更新 更多