【问题标题】:Is there a way to get the declared type of a property rather than the type of the assigned value in typescript有没有办法获取属性的声明类型而不是打字稿中分配值的类型
【发布时间】:2019-12-28 08:58:42
【问题描述】:

我正在尝试在 typescript 中创建一个可以由子模型扩展的通用模型类,以便创建自动 HTTP 数据以对超类中的处理方法进行建模。

一个基本的子模型可能是这样的:

export class User extends Model {

    private username: string = null;

    constructor () {
        super ();
        this.processJson ();
    }
}

我们的父模型类执行如下操作:

export class Model {

    constructor () {
    }

    public processJson<T> () {

        _.forEach (Object.keys (this), (key: string) => {
            console.log (`processing key: ${key}`);
            console.log (typeof this[key]);
        })
   }
}

计划是使用processJson 方法作为单个入口点来获取入站 JSON 数据并根据其定义将其处理到我们的子模型中。

这里的问题是我似乎无法获得在子模型中定义的声明类型,在提供的示例中,typeof this[key] 将返回 object,因为它推断了此分配值的类型例如null

我的计划是将其用于更复杂的情况,我们可能有更复杂的对象或具有特殊处理的不同类型,并在我们的父模型类中的一个集中位置执行所有这些。

我的问题是这样的,我怎么知道子模型的属性,得到我们username示例的声明类型为string而不是object

这是对生成的底层 JavaScript 的限制吗?还是我误解了声明的类属性在 Typescript 中是如何工作的?

我知道在将属性声明为时:

private username: string = '';

它会给我正确的类型,但我不想在它们被 JSON 数据分配之前初始化值,因为在某些情况下null 可能是一个有效值。

【问题讨论】:

    标签: angular typescript


    【解决方案1】:

    您的代码 sn-p 假定您在运行时需要打字稿的类型信息。但是,在运行时,所有类型都会被 typescript 编译器擦除。它只发出没有类型注释的纯 javascript。

    我相信你最好的选择是创建一个装饰器并用它装饰模型的每个属性 - 像这样:

    class User extends Model {
      @ModelField private username: string;
    }
    

    还要确保启用 emitDecoratorMetadata 编译器选项 (https://www.typescriptlang.org/docs/handbook/decorators.html#metadata)

    它应该允许您通过反射元数据读取修饰属性的类型(例如,如此答案中所建议:How to get type data in TypeScript decorator?)。

    【讨论】:

      【解决方案2】:

      您可以使用typeof=== 严格比较和instanceof 来检查声明的类型

      enter image description here

      【讨论】:

      • 点击enter image description here链接查看示例代码
      • 代码图像无助于任何人;请在帖子中包含您的代码。
      【解决方案3】:

      示例代码:

      class Circle {
          public kind: string = '';
          public radius: number = 0;
      }
      
      let objCircle: Circle;
      
      objCircle = { 
          kind: 'circle1', 
          radius: 123 
      } as Circle;
      
      console.log(typeof objCircle.kind === 'string')  // true
      console.log(typeof objCircle.radius === 'number') // true
      console.log(objCircle instanceof Object) // true
      
      

      【讨论】:

      • 我不相信这完全达到了我所追求的,因为这将起作用,因为它定义了属性的默认值,即''0,而我希望默认值为null
      • 如果默认值为空,则可以使用类型any,并且可以将其作为类 Circle { public kind: any = null;公共半径:数字= 0; } 让 objCircle: Circle; objCircle = { 种类:空,半径:123 } 作为圆形; console.log(typeof objCircle.kind === 'object') // true
      猜你喜欢
      • 1970-01-01
      • 2023-03-20
      • 2019-02-16
      • 2021-02-04
      • 1970-01-01
      • 2021-12-14
      • 2018-12-16
      • 1970-01-01
      • 2022-01-06
      相关资源
      最近更新 更多