'bất kỳ' so với 'Đối tượng'


209

Tôi đang xem mã TypeScript và nhận thấy rằng họ sử dụng:

interface Blablabla {

   field: Object;

}

Lợi ích của việc sử dụng Objectso với any, như trong:

interface Blablabla {

  field: any;

}

Câu trả lời:


202

Objectlà hạn chế hơn any. Ví dụ:

let a: any;
let b: Object;

a.nomethod(); // Transpiles just fine
b.nomethod(); // Error: Property 'nomethod' does not exist on type 'Object'.

Các Objectlớp học không có một nomethod()chức năng, do đó transpiler sẽ tạo ra một lỗi cho biết chính xác điều đó. Nếu bạn sử dụng anythay vì về cơ bản, bạn đang nói với bộ chuyển đổi rằng mọi thứ đều ổn, bạn sẽ không cung cấp thông tin nào về những gì được lưu trữ a- đó có thể là bất cứ điều gì! Và do đó, bộ chuyển mã sẽ cho phép bạn làm bất cứ điều gì bạn muốn với một cái gì đó được xác định là any.

Vì vậy, trong ngắn hạn

  • any có thể là bất cứ điều gì (bạn có thể gọi bất kỳ phương thức nào, v.v. mà không có lỗi biên dịch)
  • Objecttrưng ra các hàm và thuộc tính được định nghĩa trong Objectlớp.

283

Bit cũ, nhưng không đau để thêm một số ghi chú.

Khi bạn viết một cái gì đó như thế này

let a: any;
let b: Object;
let c: {};
  • a không có giao diện, nó có thể là bất cứ thứ gì, trình biên dịch không biết gì về các thành viên của nó vì vậy không có kiểm tra kiểu nào được thực hiện khi truy cập / gán cả cho nó và các thành viên của nó. Về cơ bản, bạn đang bảo trình biên dịch " lùi lại, tôi biết tôi đang làm gì, vì vậy hãy tin tôi ";
  • b có giao diện Object, vì vậy CHỈ các thành viên được xác định trong giao diện đó có sẵn cho b . Nó vẫn là JavaScript, vì vậy mọi thứ đều mở rộng Object;
  • c mở rộng Object, giống như mọi thứ khác trong TypeScript, nhưng không thêm thành viên. Vì khả năng tương thích kiểu trong TypeScript dựa trên phân nhóm cấu trúc, không phải là phân nhóm danh nghĩa, c kết thúc giống như b vì chúng có cùng giao diện: giao diện Object.

Và đó là lý do tại sao

a.doSomething(); // Ok: the compiler trusts you on that
b.doSomething(); // Error: Object has no doSomething member
c.doSomething(); // Error: c neither has doSomething nor inherits it from Object

và tại sao

a.toString(); // Ok: whatever, dude, have it your way
b.toString(); // Ok: toString is defined in Object
c.toString(); // Ok: c inherits toString from Object

Vì vậy Object{}là tương đương trong TypeScript.

Nếu bạn khai báo các hàm như thế này

function fa(param: any): void {}
function fb(param: Object): void {}

với ý định chấp nhận bất cứ điều gì cho param (có thể bạn sẽ kiểm tra các loại vào thời gian chạy để quyết định nên làm gì với nó), hãy nhớ rằng

  • Trong fa , trình biên dịch sẽ cho phép bạn làm bất cứ điều gì bạn muốn với param ;
  • bên trong fb , trình biên dịch sẽ chỉ cho phép bạn tham chiếu các thành viên của Object .

Tuy nhiên, điều đáng chú ý là nếu param được chấp nhận nhiều loại đã biết, một cách tiếp cận tốt hơn là khai báo nó bằng cách sử dụng các loại kết hợp, như trong

function fc(param: string|number): void {}

Rõ ràng, các quy tắc thừa kế OO vẫn được áp dụng, vì vậy nếu bạn muốn chấp nhận các thể hiện của các lớp dẫn xuất và xử lý chúng dựa trên loại cơ sở của chúng, như trong

interface IPerson {
    gender: string;
}

class Person implements IPerson {
    gender: string;
}

class Teacher extends Person {}

function func(person: IPerson): void {
    console.log(person.gender);
}

func(new Person());     // Ok
func(new Teacher());    // Ok
func({gender: 'male'}); // Ok
func({name: 'male'});   // Error: no gender..

loại cơ sở là cách để làm điều đó, không phải bất kỳ . Nhưng đó là OO, ngoài phạm vi, tôi chỉ muốn làm rõ rằng mọi thứ chỉ nên được sử dụng khi bạn không biết điều gì sắp xảy ra, và đối với bất cứ điều gì khác, bạn nên chú thích đúng loại.

CẬP NHẬT:

Nguyên cảo 2.2 thêm một objectloại, trong đó quy định cụ thể rằng một giá trị là một tổ chức phi nguyên thủy: (tức là không phải là một number, string, boolean, symbol, undefined, hoặc null).

Xem xét các hàm được định nghĩa là:

function b(x: Object) {}
function c(x: {}) {}
function d(x: object) {}

xsẽ có cùng các thuộc tính khả dụng trong tất cả các hàm này, nhưng đó là lỗi kiểu gọi dvới nguyên hàm:

b("foo"); //Okay
c("foo"); //Okay
d("foo"); //Error: "foo" is a primitive

2
Có ai biết tại sao họ quyết định thêm {}sau đó nếu họ đã có Object? (hoặc ngược lại, tùy theo điều kiện nào đến trước) Có một chút khác biệt, phải không?
CletusW

4
{}là cách thông thường để xác định giao diện (nội tuyến), chỉ có điều trong trường hợp này bạn đang xác định giao diện không có thành viên. Sự khác biệt nhỏ được giải thích rõ trong phản hồi: " {}mở rộng Object, giống như mọi thứ khác trong TypeScript".
DanielM

7
Tôi muốn bỏ phiếu cho bạn cho dòng Vì vậy, về cơ bản, khi bạn không biết loại, hãy đi anyvà kiểm tra loại thời gian chạy. Không sử dụng any, thay vào đó hãy sử dụng kết hợp các loại bạn đang kiểm tra : TypeA|InterfaceB|string. Nếu bạn cũng có một trường hợp mặc định cho một loại không xác định, hãy thêm {}hoặc Objectvào liên minh.
ILMTitan

Tài liệu bản thảo đôi khi khó hiểu, ví dụ But variables of type Object only allow you to assign any value to them - you can’t call arbitrary methods on them, even ones that actually exist:làm tôi nghĩ rằng ngay cả việc gọi điện toStringcũng không được phép, trong khi thực tế tôi nghĩ họ muốn nói exist at runtimesau khi đọc câu trả lời của bạn.
Olga

24

any là một cái gì đó cụ thể cho TypeScript được giải thích khá tốt bằng câu trả lời của alex.

Objectđề cập đến objectloại JavaScript . Thường được sử dụng như {}hoặc đôi khi new Object. Hầu hết mọi thứ trong javascript đều tương thích với kiểu dữ liệu đối tượng khi chúng kế thừa từ nó. Nhưng anynguyên cảo cụ thể và phù hợp với tất cả mọi thứ theo cả hai hướng (không thừa kế dựa). ví dụ :

var foo:Object; 
var bar:any;
var num:number;

foo = num; // Not an error
num = foo; // ERROR 

// Any is compatible both ways 
bar = num;
num = bar;  

1
Câu trả lời của bạn khá mơ hồ và hỗn hợp Objectobjectđó là các loại khác nhau trong TypeScript.
m93a

@ m93a: Bạn có thể mở rộng về sự khác biệt giữa Objectobjecttrong TS không?
Alexander Abakumov

4
Đây có lẽ là nguồn tốt nhất để tìm hiểu sự khác biệt. Điểm chính objectlà một loại cho tất cả mọi thứ không phải là nguyên thủy, trong khi đó Objectlà một giao diện chứa những thứ phổ biến như toStringvà như vậy. Số 42sẽ là một Objectnhưng không phải là một object.
m93a

20

Trái ngược với .NET nơi tất cả các loại xuất phát từ một "đối tượng", trong TypeScript, tất cả các loại đều xuất phát từ "bất kỳ". Tôi chỉ muốn thêm sự so sánh này vì tôi nghĩ nó sẽ là một phổ biến được thực hiện khi nhiều nhà phát triển .NET cung cấp cho TypeScript thử.


16

Đối tượng dường như là một tuyên bố cụ thể hơn bất kỳ. Từ thông số TypeScript (phần 3):

Tất cả các loại trong TypeScript là các kiểu con của một loại đầu duy nhất được gọi là Loại bất kỳ. Các từ khóa tham khảo loại này. Loại Bất kỳ là một loại có thể biểu thị bất kỳ giá trị JavaScript nào mà không có ràng buộc. Tất cả các loại khác được phân loại là loại nguyên thủy, loại đối tượng hoặc tham số loại. Những loại này giới thiệu các ràng buộc tĩnh khác nhau trên các giá trị của họ.

Cũng thế:

Loại Bất kỳ được sử dụng để đại diện cho bất kỳ giá trị JavaScript. Một giá trị của Loại bất kỳ hỗ trợ các hoạt động tương tự như một giá trị trong JavaScript và kiểm tra loại tĩnh tối thiểu được thực hiện cho các hoạt động trên Bất kỳ giá trị nào. Cụ thể, các thuộc tính của bất kỳ tên nào cũng có thể được truy cập thông qua bất kỳ giá trị nào và Mọi giá trị có thể được gọi là hàm hoặc hàm tạo với bất kỳ danh sách đối số nào.

Các đối tượng không cho phép sự linh hoạt tương tự.

Ví dụ:

var myAny : any;

myAny.Something(); // no problemo

var myObject : Object;

myObject.Something(); // Error: The property 'Something' does not exist on value of type 'Object'.

0

Thêm vào câu trả lời của Alex và đơn giản hóa nó:

Các đối tượng nghiêm ngặt hơn với việc sử dụng của chúng và do đó cung cấp cho người lập trình nhiều năng lực "đánh giá" thời gian biên dịch hơn và do đó, trong nhiều trường hợp cung cấp nhiều "khả năng kiểm tra" hơn và có thể ngăn chặn bất kỳ rò rỉ nào, trong khi đó là một thuật ngữ chung hơn và rất nhiều biên dịch kiểm tra thời gian do đó có thể bị bỏ qua.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.