2016-10-24 5 views
1

방금 ​​Typescript로 시작했는데 클래스 속성이 클래스에 선언 된 속성 외에도 임의의 속성을 보유하는 객체 일 수 있는지 이해할 수 없습니다. 예를 들어 namePerson의 속성으로 정의한 다음 properties 아래에 해당 키와 같은 다른 임의의 특성을 정의 할 수 있어야합니다. 제법클래스 속성으로 임의의 속성을 가진 객체

Property 'height' does not exist on type 'Object'

를 : 말하는 괜찮 간다 할당하지만, 라인 (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); 

인터페이스의 또 다른 대안을 , 그것은 여전히 ​​작동하지 않습니다. Person#properties의 정적 유형은 유형 검사 그것에 대해 추가 유형의 정보를 유지하지 않습니다 단순히 Object 때문에 당신이 컴파일 에러가 발생하는 이유

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()); 
+0

당신 어떤 유형 으로든 그것을 정의 할 수있다. – Geeky

답변

5

, 즉이다. 당신은이 문제를 2 가지 방법

를 해결할 수 any과 함께 "바보"방법

: TS에서

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 

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 

이 방법과 함께 약간 똑똑한 방법은 각 사람의 인스턴스는 관련 페이지를해야합니다 roperties 형식이므로 액세스하려는 속성이 컴파일러에 의해 알려진 경우 "컴파일"시간이 선택됩니다. 당신이 속성 height이없는 정말 public properties: Object;Object를 정의하고 있기 때문에 https://www.typescriptlang.org/docs/handbook/generics.html

1

오류가 발생이 다른 언어에서 익숙하지 않는 경우

내가 제네릭에 대한 몇 가지 독서를 권 해드립니다. { 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']); 
0

유형 매핑을 사용할 수 있습니다. 당신이 (UserIdentifier)와 함께 작업하고보다하는 함수 (내 예제에서 사용자 개체의 생성자)의 매개 변수에 그 혼합하려는 속성을 매핑해야합니다 모든 키 (랩)와 클래스로 구성 유형을 작성

type Wrap<T> = { 
    [P in keyof T]?: T[P] 
} 

type UserIdentifier = { 
    userId: string; 
} 

class User { 
    constructor(user: Wrap<any> & UserIdentifier) { 
     this.user = user; 
    } 
    user: Wrap<any> & UserIdentifier; 

    userId(): string { 
     return this.user.userId; 
    } 

} 

//then can be called as 
let u = new User({userId:"usr1", someOther:1, andOther:2, andSoOn:3}); 
//or just 
let u2 = new User({userId:"usr1"}); 
//however this will throw an error because required userId property is not present 
let u3 = new User({someOther:1}); 
관련 문제