【问题标题】:Typescript generics: given key K and object T, constrain the type of T[K]Typescript 泛型:给定键 K 和对象 T,约束 T[K] 的类型
【发布时间】:2019-02-02 11:11:28
【问题描述】:

我有一个环境,其中具有id 属性的某些对象每个“滴答”都会过期,需要使用getObjectById 召回。我想通过映射thing.property => getObjectById(thing.property.id) 来实现一个setter 方法来刷新某物的属性。理想情况下,我希望这种方法采用 T 和键 K,其中 T[K] 可以是具有 id (HasID) 或它们的数组 (HasID[]) 的对象。

我相信我已经接近解决方案,但还不是很正确。下面列出了我目前拥有的(名为$ 的类上的静态方法):

static refresh<T extends {[K in keyof T]: HasID}, K extends keyof T>(thing: T, key: K): void;
static refresh<T extends {[K in keyof T]: HasID[]}, K extends keyof T>(thing: T, key: K): void;
static refresh<T extends {[K in keyof T]: HasID | HasID[]}, K extends keyof T>(thing: T, key: K): void {
    if (_.isArray(thing[key])) {
        thing[key] = _.map(thing[key] as HasID[], s => getObjectById(s.id)) as HasID[];
    } else {
        thing[key] = getObjectById(thing[key].id) as HasID;
    }
}

例如,foo: {bar: HasID, baz: HasID[], biz: string[]} 的期望行为是:

$.refresh(foo, 'bar') // foo.bar = getObjectById(foo.bar.id)
$.refresh(foo, 'baz') // foo.baz = _.map(foo.baz, x=>getObjectById(x.id))
$.refresh(foo, 'biz') // error: foo.biz is not HasID or HasID[]
$.refresh(foo, 'boo') // error: 'boo' is not a key of foo

有人能指出正确的方向来正确限制T[K] 的类型吗?

【问题讨论】:

    标签: typescript generics typescript-generics


    【解决方案1】:

    你很接近,问题是T的每个键都不是HasIDHasID[],只有K指定的那个

    class $ {
      static refresh<T extends { [P in K]: HasID }, K extends string>(thing: T, key: K): void;
      static refresh<T extends { [P in K]: HasID[] }, K extends string>(thing: T, key: K): void;
      static refresh<T extends { [P in K]: HasID | HasID[] }, K extends string>(thing: T, key: K): void {
    
      }
    }
    
    let foo: { bar: HasID, baz: HasID[], biz: string[] };
    $.refresh(foo, 'bar') // foo.bar = getObjectById(foo.bar.id)
    $.refresh(foo, 'baz') // foo.baz = _.map(foo.baz, x=>getObjectById(x.id))
    $.refresh(foo, 'biz') // error: foo.biz is not HasID or HasID[]
    $.refresh(foo, 'boo') // error: 'boo' is not a key of foo
    

    您也可以使用Record&lt;K, HasId&gt; 代替{ [P in K]: HasID },我保留了您的原始版本以便更容易跟踪差异。使用记录签名将是:

    class $ {
      static refresh<T extends Record<K, HasID>, K extends string>(thing: T, key: K): void;
      static refresh<T extends Record<K, HasID>[], K extends string>(thing: T, key: K): void;
      static refresh<T extends Record<K, HasID | HasID[]>, K extends string>(thing: T, key: K): void {
    
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-11
      • 1970-01-01
      • 2017-01-21
      • 2014-11-29
      • 2019-03-21
      • 1970-01-01
      • 1970-01-01
      • 2013-08-29
      • 1970-01-01
      相关资源
      最近更新 更多