通用函数中的属性类型 [英] Type of properties in a generic function

查看:43
本文介绍了通用函数中的属性类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to transform some fields of my object by providing field names, currently I wrote something like follows:

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])上收到以下错误消息:

But I end up with the following error message on 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 Foo [T] Parameters< Bar [T]> 应该相同吗?

But shouldn't typescript "know" that with the same T, Foo[T] and Parameters<Bar[T]> should be the same?

推荐答案

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

Perhaps the compiler should know that, but it doesn't. I tend to call this issue "correlated types" or "correlated records". The compiler sees foo[field] and bar[field] as union-typed things, which is true enough. But it treats their types as independent, meaning that as far as it knows, foo[field] might be number[] while bar[field] might be a function that takes string[]. It doesn't see that the type of foo[field] is correlated to the type of bar[field] in such a way that knowing one fixes the other. There's an open issue, microsoft/TypeScript#30581 (which I filed, fwiw) suggesting that there be some support for correlated types, but it's not clear if that's ever going to happen or how.

我们现在所拥有的只是解决方法.该问题中提到的两种解决方法:要么使用冗余代码来强制编译器解决各种可能性并保证类型安全,要么使用

All we have right now are workarounds. The two workarounds mentioned in that issue: either use redundant code to force the compiler to walk through the different possibilities and guarantee type safety, or use type assertions to give up on some type safety but maintain brevity. For your code it would look like this:

// 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]);

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

I usually opt for the type assertion. Okay, hope that helps; good luck!

链接到代码

这篇关于通用函数中的属性类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆