【问题标题】:Is it possible to modify the inferred type of a literal in TypeScript?是否可以修改 TypeScript 中文字的推断类型?
【发布时间】:2020-12-14 06:15:39
【问题描述】:

考虑以下代码,它尝试有条件地将属性添加到具有推断类型的对象:

const foo = {
    a: 1,
    b: 2,
};

if (bar) {
    foo.c = 3; // Error: Property 'c' does not exist on type '{ a: number; b: number; }'.(2339)
}

可以通过将foo 的类型显式声明为{ a: number; b: number; c?: number; } 或使用扩展有条件地添加c 来消除错误:

const foo = {
    a: 1,
    b: 2,
    ...(bar ? { c: 3 } : {}),
};

但是,假设我们希望保留原始代码结构,但我们也希望避免显式声明可以推断的属性。有没有可以同时满足这两个方面的解决方案?例如,是否可以以某种方式调整推断的类型,例如:

const foo = {
    a: 1,
    b: 2,
} as { ...; c?: number; }; // Example, does not work

【问题讨论】:

    标签: typescript type-inference


    【解决方案1】:

    这并不漂亮,但它确实有效:ab 的属性类型是推断出来的,不必重复声明。

    function withMissingProps<T>() {
      return function<S>(obj: S): S & Partial<T> {
        return obj;
      }
    }
    
    const foo = withMissingProps<{ c: number }>()({
      a: 1,
      b: 2
    });
    
    if(Math.random() > 0.5) {
      foo.c = 1;
    }
    

    有两个类型参数,TS,分别用于声明和推断的属性。不幸的是,如果一个函数有两个类型参数,那么您必须同时提供或推断两者;解决方案是 curry 函数,虽然这意味着额外的一对括号。

    Playground Link

    【讨论】:

      【解决方案2】:

      我还发现了这个 hack,不幸的是它编译为 Object.assign,因此运行时成本不为零:

      const foo = {
        a: 1,
        b: 2,
        ...{} as {
          c?: number,
        },
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-12-10
        • 2013-02-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-03
        相关资源
        最近更新 更多