在打字稿中:是否有编译时间'获取TypeScript接口中定义的所有属性名称的方法是什么?

时间:2015-05-13 06:53:44

标签: javascript generics interface typescript

我想创建一个通用的TypeScript类,用于渲染(作为HTML列表)实现特定TypeScript接口的对象数组。

e.g。

class GenericListRenderer<T> {
  items: T[];

 constructor(listItems: T[], className?: string){
      this.items = listItems;
      ...
    }

    private getPropertyNames(): string[]{

    // What is the best way to access all property names defined in
    // TypeScript interface 'T' that was used in this generic?
    ...   
    }

    render(){
      var propNames: string[] = this.getPropertyNames();
      // render list with each item containing set of all 
      // key(prop name)/value pairs defined by interface 'T'  
      ...

    }
}

问:什么是获得编译时间的最佳方式?指定的()TypeScript接口中定义的所有属性名称的列表?

与C ++模板一样,我相信当TypeScript类型信息(如提供给用于实例化特定对象的泛型的接口)随时可用时,TypeScript可以在#34;编译时&#34;期间解析这些泛型。

由于可能提供了所有必需的类型信息,我只是好奇是否有可用的TypeScript扩展/工具来访问此信息而不会过度运行时过滤&#39; vanilla&#39; Javascript对象 - 由于模糊的继承问题可能会出现问题(例如,如果运行时,泛型,Javascript(obj.hasOwnProperty(prop))用于过滤属性,则可能会过滤掉所需的TypeScript继承的接口属性。)

这个有用的属性内省潜力可以通过TypeScript的超级类型元数据在编译时间内明确地解决。 vs当尝试在翻译的Javascript中解析此信息时,将丢弃所有此类型信息。

我讨厌重新发明轮子&#39;如果存在标准(TypeScript)方法,则可能存在不完善的Javascript攻击。

此致: 初学者TypeScript Guy, 约翰

4 个答案:

答案 0 :(得分:14)

这可以通过使用https://github.com/Microsoft/TypeScript/pull/13940引入的自定义变换器来实现,该变换器可以在typescript @ next中找到。

我的npm包ts-transformer-keys就是一个很好的例子。

import { keys } from 'ts-transformer-keys';

interface Props {
  id: string;
  name: string;
  age: number;
}
const keysOfProps = keys<Props>();

console.log(keysOfProps); // ['id', 'name', 'age']

答案 1 :(得分:6)

这不可能在运行时检索这些信息,除非您在编译期间存储它们,否则它们永远不会是默认的。因此,解决方案是使用ReflectDecorators进行反思。

Here是一篇很好的文章,涵盖了在运行时检索编译时元数据的问题。简而言之:你想要保留描述的接口添加一个装饰器,这个将被转换为一个json对象,一个将被存储到代码本身。在运行时,您将能够检索具有所有接口数据的此json对象。现在这是实验性的(2016年2月11日),但是很好。

注意:默认情况下永远不会出现这种情况的原因基本上是ts的设计选择,不要使用元数据重载js代码(与Dart不同)。

答案 2 :(得分:0)

您可以通过致电获取所需的所有信息

let test = Object.keys(instanceOfObject)

如果您登录此 console.log(test),则会得到类似的内容:

0: "user_id"
...
26: "address"
length: 27

您可以访问有关该对象的所有信息,例如test.length等。

发件人:https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

答案 3 :(得分:-1)

在运行时,所有类型信息都将被删除,因此您可以做的最好的事情是枚举其中一个对象的属性。这将返回所有属性,甚至是那些不在指定接口上的属性。

class GenericListRenderer<T> {

    constructor(private items: T[], private className?: string){

    }

    private getPropertyNames(): string[] {
        var properties: string[] = [];

        if (this.items.length > 0) {
            for (var propertyName in this.items[0]) {
                console.log(propertyName);
                properties.push(propertyName);
            }
        }

        return properties;
    }

    render(){
      var propNames: string[] = this.getPropertyNames();
    }

}

class Example {
    constructor(public name: string) {

    }
}

var example = new Example('Steve');

var a = new GenericListRenderer<Example>([example]);

a.render();

还有Object.keys(),它可以为您提供所有属性,但仅在IE9及更高版本中支持。

如果您可以为要对属性执行的操作提供更多用例,则可以使用属性或其他机制为您提供备用解决方案。