Làm cách nào để khai báo một kiểu là nullable trong TypeScript?


248

Tôi có một giao diện trong TypeScript.

interface Employee{
    id: number;
    name: string;
    salary: number;
}

Tôi muốn tạo salarythành một trường không thể (Giống như chúng ta có thể làm trong C #). Điều này có thể làm trong TypeScript không?

Câu trả lời:


275

Tất cả các trường trong JavaScript (và trong TypeScript) có thể có giá trị nullhoặc undefined.

Bạn có thể làm cho trường tùy chọn khác với nullable.

interface Employee1 {
    name: string;
    salary: number;
}

var a: Employee1 = { name: 'Bob', salary: 40000 }; // OK
var b: Employee1 = { name: 'Bob' }; // Not OK, you must have 'salary'
var c: Employee1 = { name: 'Bob', salary: undefined }; // OK
var d: Employee1 = { name: null, salary: undefined }; // OK

// OK
class SomeEmployeeA implements Employee1 {
    public name = 'Bob';
    public salary = 40000;
}

// Not OK: Must have 'salary'
class SomeEmployeeB implements Employee1 {
    public name: string;
}

So sánh với:

interface Employee2 {
    name: string;
    salary?: number;
}

var a: Employee2 = { name: 'Bob', salary: 40000 }; // OK
var b: Employee2 = { name: 'Bob' }; // OK
var c: Employee2 = { name: 'Bob', salary: undefined }; // OK
var d: Employee2 = { name: null, salary: 'bob' }; // Not OK, salary must be a number

// OK, but doesn't make too much sense
class SomeEmployeeA implements Employee2 {
    public name = 'Bob';
}

35
Có vẻ như các loại nullable hoàn toàn và kiểm tra null nghiêm ngặt đã được triển khai và sẽ đến với Typecript 2.0! (hoặc typescript@nextbây giờ.)
mindplay.dk

Bạn có chắc chắn về var c trong ví dụ đầu tiên không? Dường như với tôi rằng var b và var c giống nhau ở đó.
martinp999

Để đặt giá trị null hoặc không xác định mà không có lỗi biên dịch, tùy chọn "nghiêm ngặt" của tsconfig phải được xóa hoặc bằng "false""strict" : false
Nicolas Janel

1
Điều này là không đúng. JS phân biệt giữa null và không xác định. Mã chính xác phải là salary:number|null;Nếu bạn làm salary?:number; salary = null;Bạn sẽ gặp lỗi. Tuy nhiên, salary = undefined;sẽ hoạt động tốt trong trường hợp này. Giải pháp: sử dụng Union tức là '|'
Ankur Nigam

125

Loại liên minh là trong tâm trí của tôi lựa chọn tốt nhất trong trường hợp này:

interface Employee{
   id: number;
   name: string;
   salary: number | null;
}

// Both cases are valid
let employe1: Employee = { id: 1, name: 'John', salary: 100 };
let employe2: Employee = { id: 1, name: 'John', salary: null };

EDIT: Đối với điều này để làm việc như mong đợi, bạn nên kích hoạt strictNullCheckstrong tsconfig.


9
Nếu bạn sử dụng --strictNullChecks (mà bạn nên), đây là một giải pháp hợp lệ. Tôi sẽ không sử dụng nó để ủng hộ các thành viên tùy chọn, vì nó buộc bạn phải thêm một giá trị rõ ràng vào tất cả các đối tượng bằng chữ, nhưng đối với các giá trị trả về của hàm, đó là cách để đi.
geon

78

Để giống C # hơn , hãy xác định Nullableloại như thế này:

type Nullable<T> = T | null;

interface Employee{
   id: number;
   name: string;
   salary: Nullable<number>;
}

Tặng kem:

Để thực hiện Nullablehành vi giống như một kiểu Bản mô tả, hãy xác định nó trong global.d.tstệp định nghĩa trong thư mục nguồn gốc. Con đường này làm việc cho tôi:/src/global.d.ts


1
Câu trả lời yêu thích của tôi - trực tiếp trả lời câu hỏi mà không cần đọc vào đó.
Lqueryvg

1
Sử dụng điều này phá vỡ tự động hoàn thành các thuộc tính đối tượng. Ví dụ: nếu chúng ta có emp: Partial<Employee>, chúng ta có thể làm emp.idhoặc emp.namevân vân nhưng nếu có emp: Nullable<Employee>, chúng ta không thể làm đượcemp.id
Yousuf Khan

1
Đây là câu trả lời thực tế cho câu hỏi.
Patrick

36

Chỉ cần thêm một dấu hỏi ?vào trường tùy chọn.

interface Employee{
   id: number;
   name: string;
   salary?: number;
}

54
Như Ryan đã chỉ ra ...? có nghĩa là tùy chọn trong bản thảo, không phải là nullable. Không có ? có nghĩa là var phải được đặt thành một giá trị bao gồm null hoặc không xác định. Với ? bạn có thể bỏ qua toàn bộ khai báo.
Anh Nrik

3
Cảm ơn bạn! Tôi đã googled cho "giá trị tùy chọn bản thảo" vì vậy đây chính xác là những gì tôi đang tìm kiếm.
Người lạ

13

Bạn chỉ có thể thực hiện một loại do người dùng xác định như sau:

type Nullable<T> = T | undefined | null;

var foo: Nullable<number> = 10; // ok
var bar: Nullable<number> = true; // type 'true' is not assignable to type 'Nullable<number>'
var baz: Nullable<number> = null; // ok

var arr1: Nullable<Array<number>> = [1,2]; // ok
var obj: Nullable<Object> = {}; // ok

 // Type 'number[]' is not assignable to type 'string[]'. 
 // Type 'number' is not assignable to type 'string'
var arr2: Nullable<Array<string>> = [1,2];


4

tôi đã có cùng một câu hỏi một lúc trước .. tất cả các loại trong ts là nullable, bởi vì void là một kiểu con của tất cả các loại (không giống như, ví dụ, scala).

xem liệu lưu đồ này có giúp được không - https://github.com/bcherny/lingu-types-comparison#typescript


2
-1: Điều này không đúng chút nào. Đối với void'loại phụ của tất cả các loại' ( loại dưới cùng ), hãy tham khảo chủ đề này . Ngoài ra biểu đồ bạn cung cấp cho scala là không chính xác. Nothingtrong scala, trên thực tế, là loại dưới cùng. Bản đánh máy, atm, không có loại dưới cùng trong khi scala thì có .
Daniel Shin

2
"Subtype của tất cả các loại"! = Loại dưới cùng. Xem thông số kỹ thuật TS tại đây github.com/Microsoft/TypeScript/blob/master/doc/iêu
bcherny

3

Loại Nullable có thể gọi lỗi thời gian chạy. Vì vậy, tôi nghĩ rằng tốt để sử dụng một tùy chọn trình biên dịch --strictNullChecksvà khai báo number | nulllà loại. cũng trong trường hợp hàm lồng nhau, mặc dù kiểu đầu vào là null, trình biên dịch không thể biết nó có thể phá vỡ cái gì, vì vậy tôi khuyên bạn nên sử dụng !(dấu chấm than).

function broken(name: string | null): string {
  function postfix(epithet: string) {
    return name.charAt(0) + '.  the ' + epithet; // error, 'name' is possibly null
  }
  name = name || "Bob";
  return postfix("great");
}

function fixed(name: string | null): string {
  function postfix(epithet: string) {
    return name!.charAt(0) + '.  the ' + epithet; // ok
  }
  name = name || "Bob";
  return postfix("great");
}

Tài liệu tham khảo. https://www.typescriptlang.org/docs/handbook/advified-types.html#type-guards-and-type-assertions

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.