2016-03-24 14 views
7

Tôi đang cố gắng để thiết lập một tiểu hữu first được định nghĩa trong giao diện Name nhưng khi làm như vậy tôi luôn luôn nhận được một lỗi ví dụ:Trong nguyên cảo làm thế nào để khắc phục không thể đặt thuộc tính 'đầu tiên' không xác định

interface Name{ 
    first: string, 
    last:string, 
} 

class Person{ 

    private name:Name 

    public setName(firstName, lastName){ 
     this.name.first = firstName; 
     this.name.last = lastName; 
    } 

} 


var person1 = new Person(); 
person1.setName('Tracy','Herrera'); 

Khi chạy nó tôi gặp lỗi: Cannot set property 'first' of undefined

Có ai có ý tưởng làm việc này không?

Trả lời

14

tính Lớp không tự động khởi tạo trên instantiation. Bạn cần phải khởi tạo chúng với các đối tượng tương ứng bằng tay - trong trường hợp này, với một đối tượng chứa các thuộc tính được định nghĩa bởi giao diện của nó:

class Person { 
    private name: Name; 

    public setName(firstName, lastName) { 
     this.name = { 
      first: firstName, 
      last: lastName 
     }; 
    } 
} 

cách tiếp cận khác - ví dụ, trong trường hợp có nhiều phương pháp thuộc tính thiết lập trên cùng một đối tượng - là lần đầu tiên khởi tạo tài sản cho một đối tượng rỗng, tốt nhất trong các nhà xây dựng:

class Person { 
    private name: Name; 

    constructor() { 
     this.name = {}; 
    } 

    public setName(firstName, lastName) { 
     this.name.first = firstName; 
     this.name.last = lastName; 
    } 

    public setFirstName(firstName) { 
     this.name.first = firstName; 
    } 
} 

Tuy nhiên, với các thiết lập hiện tại này sẽ mang lại một lỗi biên dịch khi giao {} để this.name, vì giao diện Nameyêu cầu sự hiện diện của một first và thuộc tính last trên đối tượng. Để khắc phục lỗi này, người ta có thể nghỉ mát để xác định tùy chọn tài sản trên một giao diện:

interface Name { 
    first?: string; 
    last?: string; 
} 
+0

Cảm ơn phản ứng nhanh, nhưng vấn đề với điều này là tôi có một vật thể rất lớn và làm theo cách đó khiến nó không thể đọc được dễ dàng khi chỉ có hai. bất kỳ đề xuất? –

+0

điều này là tuyệt vời, nhưng điều này sẽ làm việc tốt khi bạn có một đối tượng cấp duy nhất, nhưng khi đối tượng quá sâu như 'var info = {name: {first:" someName ", cuối cùng:" someLastName "}}' Tôi cần để init mỗi cấp độ như 'info.name = {}' và sau đó gán 'first' và' last' –

4

Bạn cần đặt tên thành đối tượng thuộc loại Tên (nghĩa là hình dạng khớp với giao diện đó).

Ví dụ:

this.name = { 
    first: 'John', 
    last: 'Doe' 
} 
+1

Cảm ơn bạn đã hữu ích –

+0

Tuyệt vời, vui lòng đánh dấu là câu trả lời. :) –

2

nếu bạn muốn có tự do, để thực hiện thay đổi, riêng biệt, bạn có thể làm điều gì đó như thế nào, sử dụng ?,

interface Name{ 
    first?: string; 
    last? : string; 
} 

class Person{ 

    private name:Name 

     public setName(firstName: string, lastName: string){ 
      this.name = { first: firstName, last: lastName }; 
     } 

     public setNameSample(firstName: string){ 
      this.name = { first: firstName }; 
     } 

     public setNameSample1(lastName: string){ 
      this.name = { last: lastName }; 
     } 
} 

trong trường hợp trên nếu bạn không sử dụng ? bạn sẽ nhận được một cái gì đó giống như trong setNameSample ví dụ nếu bạn cần thiết lập chỉ first:

Type '{ first: any; }' is not assignable to type 'Name'. Property 'last' is missing in

Lưu ý: Tôi nghĩ câu trả lời trước là cách để đi, đây chỉ là phần bổ sung.

+1

Thực ra đây là một cách hay để làm điều đó, cảm ơn –

Các vấn đề liên quan