【问题标题】:Declare object with same keys as other使用与其他相同的键声明对象
【发布时间】:2020-11-28 20:16:53
【问题描述】:

我想声明一个对象到另一个对象的映射。

第一个对象可以有任何字符串键和泛型类型的值。

我想用相同的键映射这个对象,值的类型可以是任何类型(但如果我能从泛型中提取它们就好了)。具体来说,这些是类的属性,第一个是在构造函数中传递的。

class C {
  ob1: {
    [key: string]: Wrapper<any>
  };
  ob2; // should have the same keys as ob1

  constructor(o?: { [key: string]: Wrapper<any> }) {
    this.ob1 = o;
    // map ob2 from o
  }
}

【问题讨论】:

    标签: typescript typescript-typings


    【解决方案1】:

    我认为这样做的方法是使C本身成为generic类,其类型参数T对应ob1ob2的类型,然后使用mapped types表达“相同的键但不同/相关的值”。例如:

    type MappedWrapper<T> = { [K in keyof T]: Wrapper<T[K]> }
    class C<T> {
      ob1: MappedWrapper<T>
      ob2: T;
      constructor(o: MappedWrapper<T>) { // made param required here
        this.ob1 = o;
        this.ob2 = mapUnwrap(o); // some function that unwraps properties
      }
    }
    

    这里我们说Tob2 的类型,而ob1 的类型是MappedWrapper&lt;T&gt;,这是一个映射类型,其中ob1 的每个属性都映射到一个Wrapper-版本。


    取决于Wrapper及相关类型的实现和声明,如:

    type Wrapper<T> = { x: T };
    function wrap<T>(x: T): Wrapper<T> {
      return { x };
    }
    function unwrap<T>(x: Wrapper<T>): T {
      return x.x;
    }
    function mapUnwrap<T>(x: MappedWrapper<T>): T {
      return Object.fromEntries(Object.entries(x).map(([k, v]) => [k, unwrap(v)])) as any as T;
    }
    

    您可以验证这是否按预期工作:

    const c = new C({ a: wrap(123), b: wrap("hello"), c: wrap(true) });
    /* const c: C<{ a: number; b: string; c: boolean;}> */
    
    c.ob1.a.x.toFixed(); // no error
    c.ob2.b.toUpperCase(); // no error
    

    Playground link to code

    【讨论】:

    • 我似乎无法让它与子类一起使用,然后我在构造函数中说 class Sub&lt;T&gt; extends C&lt;T&gt; 它告诉我属性在 MappedWrapper&lt;T&gt; 上不存在
    • 我需要一个minimal reproducible example 才能知道那里发生了什么。
    • 修改了你的例子,添加class Sub&lt;T&gt; extends C&lt;T&gt; { constructor() { super({ a: wrap(2) }) } }
    • 所以也许你想要class Sub extends C&lt;{ a: number }&gt; {...} 代替?
    • 是的,但是我的包装器需要更多参数,所以我不可能自动包装它
    猜你喜欢
    • 1970-01-01
    • 2012-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-25
    • 2020-08-10
    相关资源
    最近更新 更多