【问题标题】:Type of properties in a generic function泛型函数中的属性类型
【发布时间】:2020-03-23 10:39:34
【问题描述】:

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

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'

但是打字稿不应该“知道”相同的TFoo[T]Parameters&lt;Bar[T]&gt; 应该是相同的吗?

【问题讨论】:

标签: typescript generics types


【解决方案1】:

也许编译器应该知道这一点,但它不知道。我倾向于将此问题称为“相关类型”或“相关记录”。编译器将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

【讨论】:

    猜你喜欢
    • 2011-10-08
    • 2019-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多