TypeScript **功能请求** :将 fieldof 修改为类似于 keyof,但包括私有和受保护的字段,

0md85ypi  于 5个月前  发布在  TypeScript
关注(0)|答案(2)|浏览(62)

建议

🔍 搜索词

fieldof , mapped type, mapped private protected
可能相关的: #35416#4822

✅ 可实现性检查清单

我的建议满足以下准则:

  • ✅ 这不会对现有的TypeScript/JavaScript代码造成破坏性的更改
  • ✅ 这不会改变现有JavaScript代码的运行时行为
  • ✅ 可以在不根据表达式的类型发出不同的JS的情况下实现
  • [ ?]这不是一个运行时特性(例如库功能、带有JavaScript输出的非ECMAScript语法、JS的新语法糖等)
  • [ ?]这个特性将与 TypeScript's Design Goals 的其他部分一致。

⭐ 建议

为方便地Map所有包含 fieldof、private 和 protected 的键添加一个新的实用程序 fieldof

📃 动机示例

我在这里也遇到了类似的问题,一些模式使事情变得复杂!

type Writable<T> = { -readonly [P in keyof T]: T[P] }; // make writable A.parent for Childrable

class A {
  public readonly parent?: A
  protected Renderer() { };
}

// in this context, let say is a component added to A (plugin), with some method authorized to write on A.
class Childrable {
  public entity!: A;
  public readonly children: A[] = [];

  public addChild(...children: Writable<A>[]) {
    if (children.length > 1) {
      for (const child of children) this.addChild(child);
    } else {
      const child = children[0];

      if (child) {
        // So Writable<A> allow replace A.parent
        child.parent = this.entity;
        // But Writable<A> seem remove protected.Renderer prototype and now they are not compatible
        // I need allow replace A.parent and add A in Childrable.children in the same scope !
        this.children.push(child);
      }
    }

    return this;
  }
}

playground
当我们为特定情况Map类型时,希望能够轻松处理更多使用 protected , private 字段的模式。
在我上面的示例中, Childrable 是一个组件,您可以将其附加到 Entity A 上,而 Childrable 具有允许从 A 写入某些 readOnly field 的方法。
但是将它们Map为只读将删除 private 和 protected 字段并引发问题,在这种情况下, fieldof 将解决这个问题,因为我们希望允许可写,在组件中有方法来修改实体。

💻 用例

type Writable<T> = { -readonly [P in fieldof T]: T[P] };

就像 keyof 一样,但包括特定模式的所有 privateprotected 字段。
这也可能解锁更强大的功能和模式,但现在先谈谈这个特定的情况。

6rqinv9w

6rqinv9w1#

我唯一能想象到这个特性可能有用的情况是,允许 Required<X>Writable<X> 被分配给具有受保护字段的任何类 XX。在其他情况下,这将破坏受保护方法的最基本用例,因为受保护字段是在类之间检查碰撞而不是可分配性的。

关于你的情况,你声明 A.parentreadonly,这意味着它不应该在构造函数之外被分配,而你正在请求一个功能来真正允许你打破这一保证,所以即使对于 Writable 的情况,我也认为这不是一个好主意。

我非常确定你只是想要参数是 A 而不是 Writable<A>,这样外部用户可以传递实际示例,然后在方法内部使用类型Assert来允许你修改属性,尽管根据 A 的声明这是不允许的。playground

class Childrable {
  public entity!: A;
  public readonly children: A[] = [];

  public addChild(...children: A[]) {
    // ...
      const child = children[0];
      if (child) {
        // use type assertion here to indicate we are breaking the declared type in A 
        (child as Writable<A>).parent = this.entity;
        this.children.push(child);
      }
    return this;
  }
}
nzrxty8p

nzrxty8p2#

我通过抽象类找到了一个方法useWritable(),但仍然很有趣能够提取所有字段。我不是类型Assert表达式的粉丝,因为它会影响可读性。

相关问题