typescript - 泛型函数中的属性类型

标签 typescript generics types

我正在尝试通过提供字段名称来转换对象的某些字段,目前我写了如下内容:

interface Foo {
    a: number[],
    b: string[],
}

type Bar = { [T in keyof Foo] : (arg : Foo[T]) => Foo[T] }

function test<T extends keyof Foo>(field: T) {
    const foo : Foo = {
        a: [],
        b: [],
    };

    const bar: Bar = {
        a: arg => /* some code */ [],
        b: arg => /* some code */ [],
    };

    foo[field] = bar[field](foo[field]);
}

但我最终在 bar[field](foo[field]) 上收到以下错误消息:

Argument of type 'Foo[T]' is not assignable to parameter of type 'number[] & string[]'.
  Type 'number[] | string[]' is not assignable to type 'number[] & string[]'.
    Type 'number[]' is not assignable to type 'number[] & string[]'.
      Type 'number[]' is not assignable to type 'string[]'.
        Type 'number' is not assignable to type 'string'.
          Type 'Foo[T]' is not assignable to type 'number[]'.
            Type 'number[] | string[]' is not assignable to type 'number[]'.
              Type 'string[]' is not assignable to type 'number[]'.
                Type 'string' is not assignable to type 'number'

但不应该用相同的 T typescript “知道”这一点, Foo[T]Parameters<Bar[T]>应该是一样的吧?

最佳答案

也许编译器应该知道这一点,但它不知道。我倾向于将这个问题称为“相关类型”或“相关记录”。编译器将 foo[field]bar[field] 视为联合类型的东西,这是事实。但它将它们的类型视为独立的,这意味着据其所知,foo[field] 可能是 number[],而 bar[field] > 可能是一个采用string[] 的函数。它没有看到 foo[field] 的类型与 bar[field] 的类型相关,从而知道一个修复另一个。有一个悬而未决的问题,microsoft/TypeScript#30581 (我提交的,fwiw)建议对相关类型提供一些支持,但尚不清楚这是否会发生或如何发生。

我们现在拥有的只是解决方法。该问题中提到的两种解决方法:要么使用冗余代码强制编译器遍历不同的可能性并保证类型安全,要么使用 type assertions放弃某种类型安全性但保持简洁。对于您的代码,它看起来像这样:

// redundant code
const f: keyof Foo = field;
switch (f) {
   case "a":
      foo[f] = bar[f](foo[f]);
      break;
   case "b":
      foo[f] = bar[f](foo[f]);
      break;
}

// type assertion
foo[field] = (bar[field] as <T>(arg: T) => T)(foo[field]);

我通常选择类型断言。好的,希望有帮助;祝你好运!

Link to code

关于typescript - 泛型函数中的属性类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59077562/

相关文章:

reflection - 是否可以使用其中一种方法获取结构的名称?

float 与隐式和显式转换的 "f"关键字的 C# 解释

javascript - clearInterval 不适用于句柄

typescript - 为什么 TypeScript 数组是协变的?

reactjs - 将 ts-jest 与 create-react-app 一起使用

保存 ArrayList 时由泛型引起的 Java 编译器警告

javascript - 打开带有图像的模态

c# - 将 Expression<T, string>> 转换为 Expression<T, bool>>

c# - 使用yield return 返回继承基类型的对象

c - 如何检查双*数组?