具有任意属性的对象作为类属性

时间:2016-10-24 16:29:12

标签: typescript

我刚刚开始使用Typescript,我无法理解是否可以将一个类属性作为一个对象,除了在类中声明的属性之外,它还包含任何属性。例如,我在此处将name定义为Person的属性,然后在properties下,您应该能够为此人定义任何其他任意特征,例如其高度。似乎分配它没关系,但尝试在第12行访问它会引发错误说:

  

“对象”类型

上不存在属性“高度”

足够公平!我知道不能保证一个名为height的属性会出现在一个只是一个对象的东西之下,但仍然应该有办法做到这一点。

以下是代码:

class Person {
    public name: string;
    public properties: Object; 
    constructor(name: string, other: Object) {
        this.name = name;
        this.properties = other;
    }
}

let props: Object = { height: 200 };
var nick = new Person("Bob", props);
console.log(nick.properties.height);

这是我尝试的另一种选择,它会引发完全相同的错误:

class Person {
    public name: string;
    public properties: Object; 
    constructor(name: string, other:{ height: number }) {
        this.name = name;
        this.properties = other;
    }
}


var nick = new Person("Bob", { height: 200 });
console.log(nick.properties.height);

另一种选择我刚试过的界面,但仍无效。

interface PersonProperties {
    height: number;
}

class Person {
    public name: string;
    public properties: Object; 
    constructor(name: string, other: PersonProperties) {
        this.name = name;
        this.properties = other;
    }
    getHeight(): number {
        return this.properties.height;
    }
}

var properties: PersonProperties = { height: 200 }; 
var nick = new Person("Bob", properties);
document.write(nick.getHeight().toString());

2 个答案:

答案 0 :(得分:5)

由于Person#properties的静态类型只是Object,因此类型检查器不会保留任何关于它的其他类型信息,这就是编译错误的原因。您可以通过两种方式解决此问题

any的“愚蠢”方式:

class Person {
  constructor(public name: string, public other: any) {}
  /* ... */
}

const p = new Person("doge", { wow : "such property" })
console.log(p.other.wow) // no error, also no type checking
ts中的{p> any基本上“禁用”类型检查,并允许您访问键入为any的变量的任何属性

使用泛型的方式稍微聪明一些

class Person<PropType> {
  constructor(public name: string, public other: PropType) {}
}

const p = new Person("doge", { wow : "such property" })
console.log(p.other.wow) // ok
console.log(p.other.amaze) // error

这样每个人实例都有一个关联的属性类型,因此如果编译器知道您尝试访问的属性,则会检查“编译”时间。

如果其他语言看起来不熟悉,我建议您阅读一些关于泛型的内容:https://www.typescriptlang.org/docs/handbook/generics.html

答案 1 :(得分:1)

错误的发生是因为您定义了public properties: Object;Object确实没有属性height。即使您在{ height: number }属性properties的构造函数中声明了正确的类型,仍然应该是Object

你可以这样做:

type PropertiesObject = { height: number };

class Person {
    public name: string;
    public properties: PropertiesObject; 
    constructor(name: string, other: PropertiesObject) {
        this.name = name;
        this.properties = other;
    }
}

let props = <PropertiesObject>{ height: 200 };
var nick = new Person("Bob", props);
console.log(nick.properties.height);

使用界面也是正确的。

See live demo

请注意,您始终可以使用旧的方括号表示法。即使只使用Object

,这也应该成功编译
console.log(nick.properties['height']);