typescript - 如何在运行时将联合限制为一种给定类型?

标签 typescript typescript-typings

我希望能够创建一个函数工厂来更新 Redux 存储的子部分。在下面的示例中,编译器提示 state[key] 可能是一个联合。有没有办法在运行时将 K 限制为 "foo""bar"

interface State {
  foo: number[];
  bar: string[];
}

const createUpdater = <K extends keyof State>(key: K) => (
  state: State,
  id: number,
  updater: (subState: State[K][number]) => State[K][number]
) => {
  const elements: State[K] = [...state[key]]; // <--- Error
  elements[id] = updater(elements[id]);
  return {
    ...state,
    [key]: elements
  };
};

const fooUpdater = createUpdater("foo");
const barUpdater = createUpdater("bar");

错误消息:

Type '(string | number)[]' is not assignable to type 'State[K]'.
  Type '(string | number)[]' is not assignable to type 'number[] & string[]'.
    Type '(string | number)[]' is not assignable to type 'number[]'.
      Type 'string | number' is not assignable to type 'number'.
        Type 'string' is not assignable to type 'number'.ts(2322)

最佳答案

基于TypeScript Playground ,这是 3.5.1 中的问题,但在 3.6.3 和 ES7-beta 中仅在 ES3/ES5 目标中:ES2015 及更高版本似乎没问题。在这两种情况下,K 都被适本地限制为 K extends "foo" | "bar" 。目标级别更改导致类型推断错误这一事实使我认为这是一个错误。

这可能与 TS 3.5's "Smarter Union Type Checking" 有关,但听起来与 TS 3.6's "More Accurate Array Spread" 更相关,特别是考虑到 ES5 中生成的代码使用 __spreadArray .

作为解决方法,您可以使用类型断言来说服 TypeScript state[key]可以复制为State[K] ,但如“更准确的数组传播”部分 slice 中所述语义与您的传播略有不同。

const elements = state[key].slice() as State[K];

关于typescript - 如何在运行时将联合限制为一种给定类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58328115/

相关文章:

npm - Ionic 2 升级放置打字的位置

reactjs - 使用 vscode react typescript 导入语法问题

javascript - slim typescript 上的 slim 自定义事件

javascript - 找不到 TypeScript 属性错误 :

TypeScript keyof 和 Indexer 兼容性?

Angular 2 : How to execute javascript code that manipulates the DOM from a template?

node.js - 如何在发布 NPM 模块时管理外部 .d.ts 依赖项?

typescript - 尝试将多个 keyof 分配给 Typescript 中的动态描述对象

angular - 如何在 Angular 中检测具有相同值 @Input() 的变化?

typescript - 在接口(interface)中使用胖箭头和非胖箭头语法声明函数有什么区别?