Come dichiarare un tipo come nullable in TypeScript?


249

Ho un'interfaccia in TypeScript.

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

Vorrei creare salaryun campo nullable (come possiamo fare in C #). È possibile farlo in TypeScript?

Risposte:


277

Tutti i campi in JavaScript (e in TypeScript) possono avere il valore nullo undefined.

È possibile rendere facoltativo il campo diverso da 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;
}

Confrontare con:

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
Sembra che siano stati implementati tipi strettamente nullable e rigorosi controlli null che arriveranno con Typescript 2.0! (o typescript@nextora.)
mindplay.dk

sei sicuro di var c nel primo esempio? Mi sembra che var b e var c siano le stesse lì.
martinp999,

Per impostare un valore nullo o indefinito senza errore di compilazione, l'opzione "rigorosa" di tsconfig deve essere rimossa o uguale a "falso""strict" : false
Nicolas Janel,

1
Questo non è corretto JS distingue tra null e indefinito. Il codice corretto dovrebbe essere salary:number|null;Se lo fai salary?:number; salary = null;Riceverai un errore. Tuttavia, salary = undefined;funzionerà bene in questo caso. Soluzione: utilizzare Union, ovvero "|"
Ankur Nigam,

126

Il tipo di unione è nella mia mente l'opzione migliore in questo caso:

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: affinché questo funzioni come previsto, è necessario abilitare strictNullChecksin tsconfig.


9
Se usi --strictNullChecks (che dovresti), questa è una soluzione valida. Non lo userei a favore dei membri facoltativi, poiché ti costringe ad aggiungere un null esplicito su tutti gli oggetti letterali, ma per i valori di ritorno della funzione, è la strada da percorrere.
geon,

78

Per essere più simile a C # , definisci il Nullabletipo in questo modo:

type Nullable<T> = T | null;

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

Bonus:

Per Nullablecomportarsi come un tipo Typescript incorporato, definirlo in un global.d.tsfile di definizione nella cartella di origine principale. Questo percorso ha funzionato per me:/src/global.d.ts


1
La mia risposta preferita: risponde direttamente alla domanda senza leggerla.
Lqueryvg,

1
L'uso di questo interrompe il completamento automatico delle proprietà dell'oggetto. Ad esempio, se abbiamo emp: Partial<Employee>, possiamo fare emp.ido emp.nameecc, ma se abbiamo emp: Nullable<Employee>, non possiamo farloemp.id
Yousuf Khan

1
Questa è la risposta effettiva alla domanda.
Patrick,

37

Aggiungi un punto interrogativo ?al campo opzionale.

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

54
Come ha sottolineato Ryan ...? significa facoltativo in dattiloscritto, non nullable. Senza ? significa che var deve essere impostato su un valore compreso tra null o indefinito. Con ? puoi saltare l'intera dichiarazione.
Ha Nrik il

3
Grazie! Ho cercato su Google "valore facoltativo dattiloscritto", quindi questo è esattamente quello che stavo cercando.
Fellow Stranger,

13

Puoi semplicemente implementare un tipo definito dall'utente come il seguente:

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];

10
type MyProps = {
  workoutType: string | null;
};

4

ho avuto la stessa domanda qualche tempo fa .. tutti i tipi in ts sono nullable, perché void è un sottotipo di tutti i tipi (a differenza, ad esempio, di scala).

vedere se questo diagramma di flusso aiuta - https://github.com/bcherny/language-types-comparison#typescript


2
-1: questo non è affatto vero. Per quanto riguarda l' voidessere "sottotipo di tutti i tipi" ( tipo inferiore ), fare riferimento a questa discussione . Anche il grafico fornito per scala non è corretto. Nothingin scala è, infatti, il tipo di fondo. Typescript, atm, non ha un tipo bottom mentre Scala lo ha .
Daniel Shin,

2
"Sottotipo di tutti i tipi"! = Tipo di fondo. Vedi le specifiche TS qui github.com/Microsoft/TypeScript/blob/master/doc/…
bcherny,

3

Il tipo nullable può invocare un errore di runtime. Quindi penso che sia buono usare un'opzione del compilatore --strictNullCheckse dichiarare number | nullcome tipo. anche in caso di funzione annidata, sebbene il tipo di input sia nullo, il compilatore non può sapere che cosa potrebbe rompersi, quindi consiglio l'uso !(punto esclamativo).

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");
}

Riferimento. https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-type-assertions

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.