有没有一种方法可以获取属性的声明类型,而不是打字稿中的赋值类型

时间:2019-12-27 22:33:38

标签: angular typescript

我正在尝试在打字稿中创建一个通用模型类,该子类可以扩展该类,以便在超类中创建自动HTTP数据以对模型处理方法。

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

export class User extends Model {

    private username: string = null;

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

让我们的父Model类做类似的事情:

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 NOT string的形式获取object示例的声明类型?

这是对生成的基础JavaScript的限制吗?还是我误解了声明的类属性在Typescript中的工作方式?

我知道在将属性声明为:

private username: string = '';

它将为我提供正确的类型,但是在某些情况下,null可能是有效值,因此我不希望初始化这些值,因为它们是由JSON数据分配的。

3 个答案:

答案 0 :(得分:3)

您的代码段假定您在运行时需要打字稿的类型信息。但是,在运行时,所有类型都会被Typescript编译器擦除。它只会发出不带类型注释的普通javascript。

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

class Cylinders extends React.Component {

  constructor(props) {
    super(props);
    this.myRef = React.createRef();

    this.state = {
      divs: [
        { 
          className: 'hat1'
        },
        { 
          className: 'hat2'
        },
        { 
          className: 'hat3'
        }
      ]
    }
  }


  componentDidMount = () => {
    console.log('mount');
  }

  handleClick = (item, i) => {
    console.log('item', item);
    console.log('i', i);

    var divCoordinates = ReactDOM.findDOMNode(this).getBoundingClientRect();
    console.log(divCoordinates, 'divCoordinates');

   // const node = this.myRef.current;
   // console.log('node', node);
  }

  render() {
    return (
        <section>

          <div className="columns is-mobile">
            <div className="column">
              <h1 className="title has-text-black is-size-2">Cylinders Game</h1>
              <button className="has-text-black">Ball container</button>
            </div>
          </div>

          <div className="columns is-mobile">
            <div className="colum ballContainer">
              <div className="ball"></div>
            </div>
          </div>

          <div className="columns is-mobile">

            {this.state.divs.map((item, i) => {
              return (
                <div className="column">
                  <div className="columns is-multiline">
                    <div
                      onClick={() => this.handleClick(item, i)}
                      className={item.className}
                      key={item.name + i}
                      ref={el => this.containerLine = el}
                    > {i}
                    </div>
                  </div>
                </div>
              )
            })}

          </div>
        </section>
    );
  }
}

export default Cylinders;

还要确保启用[typeaheadMinLength]="0" 编译器选项(https://www.typescriptlang.org/docs/handbook/decorators.html#metadata

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

答案 1 :(得分:0)

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

enter image description here

答案 2 :(得分:0)

示例代码:

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