【问题标题】:TypeScript const assertion: Avoid type widening inside functionTypeScript const 断言:避免在函数内部扩大类型
【发布时间】:2022-11-24 01:40:48
【问题描述】:

我有以下带有 const assertion 的对象:

const foo = {
  bar: ['a', 'b'],
} as const;

我的目标是编写一个函数来更新 bar 数组并正确推断新类型。

当我将 foo.bar 传递给函数时,我可以达到预期的结果:

type Bar = Readonly<string[]>;

function update<T extends Bar>(arr: T) {
  return {
    bar: [...arr, 'c'],
  } as const;
}

const updatedFoo = update(foo.bar);

// Inferred type is as expected:
//
// const updatedFoo: {
//  readonly bar: readonly ["a", "b", "c"];
// }

但是当我传入 foo 本身时,我无法让它工作:

type Foo = Readonly<{ bar: Bar }>;

function update2<T extends Foo>(obj: T) {
  return {
    bar: [...obj.bar, 'c'],
  } as const;
}

const updatedFoo2 = update2(foo);

// Inferred type is too wide:
//
// const updatedFoo2: {
//   readonly bar: readonly [...string[], "c"];
// }

如何重写 update2 以正确推断 bar 的类型为 readonly ["a", "b", "c"]

【问题讨论】:

    标签: typescript typescript-types


    【解决方案1】:

    最简单的解决方案可能是继续使用 T 来表示 bar 的类型。我们可以为参数obj提供一个对象类型,该对象类型具有T类型的属性bar

    function update2<T extends Bar>(obj: { bar: T }) {
      return {
        bar: [...obj.bar, 'c'],
      } as const;
    }
    
    const updatedFoo2 = update2(foo);
    
    // const updatedFoo2: {
    //     readonly bar: readonly ["a", "b", "c"];
    // }
    

    如果您想将整个obj 类型用作T,则必须使用类型断言。

    function update2<T extends Foo>(obj: T) {
      return {
        bar: [...obj.bar as T["bar"], 'c'],
      } as const;
    }
    

    Playground

    【讨论】:

      猜你喜欢
      • 2020-12-15
      • 1970-01-01
      • 1970-01-01
      • 2021-05-13
      • 1970-01-01
      • 1970-01-01
      • 2019-08-21
      • 2021-12-08
      • 2018-12-31
      相关资源
      最近更新 更多