Wie deklariere ich einen Typ in TypeScript als nullbar?

248

Ich habe eine Schnittstelle in TypeScript.

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

Ich möchte salaryals nullbares Feld erstellen (wie wir es in C # tun können). Ist dies in TypeScript möglich?

Amitabh
quelle

Antworten:

275

Alle Felder in JavaScript (und in TypeScript) können den Wert nulloder haben undefined.

Sie können das Feld optional machen, das sich von nullable unterscheidet.

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

Vergleichen mit:

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';
}
Ryan Cavanaugh
quelle
35
Es sieht so aus, als ob streng nullbare Typen und strenge Nullprüfungen implementiert wurden und mit Typescript 2.0 eintreffen werden! (oder typescript@nextjetzt.)
mindplay.dk
Sind Sie sich über var c im ersten Beispiel sicher? Es scheint mir, dass var b und var c dort gleich sind.
Martinp999
Um null oder einen undefinierten Wert ohne Kompilierungsfehler zu setzen, muss die Option tsconfig "strict" entfernt werden oder gleich "false" sein"strict" : false
Nicolas Janel
1
Das ist falsch. JS unterscheidet zwischen null und undefiniert. Der richtige Code sollte lauten. salary:number|null;Wenn Sie dies tun, salary?:number; salary = null;wird eine Fehlermeldung angezeigt. Funktioniert jedoch salary = undefined;in diesem Fall einwandfrei. Lösung: Verwenden Sie Union, dh '|'
Ankur Nigam
125

Unionstyp ist meiner Meinung nach die beste Option in diesem Fall:

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: Damit dies funktioniert wie erwartet, sollten Sie die Freigabe strictNullChecksin tsconfig.

bjaksic
quelle
9
Wenn Sie --strictNullChecks verwenden (was Sie sollten), ist dies eine gültige Lösung. Ich würde es nicht zugunsten optionaler Mitglieder verwenden, da es Sie zwingt, allen Literalobjekten eine explizite Null hinzuzufügen, aber für Funktionsrückgabewerte ist es der richtige Weg.
Geon
78

Um C # ähnlicher zu sein, definieren Sie den NullableTyp folgendermaßen:

type Nullable<T> = T | null;

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

Bonus:

Um Nullablesich wie ein integrierter Typescript-Typ zu verhalten, definieren Sie ihn in einer global.d.tsDefinitionsdatei im Stammquellordner. Dieser Weg hat bei mir funktioniert:/src/global.d.ts

Tim Santeford
quelle
1
Meine Lieblingsantwort - beantwortet die Frage direkt , ohne sie zu lesen.
Lqueryvg
1
Dadurch wird die automatische Vervollständigung von Objekteigenschaften unterbrochen. Zum Beispiel, wenn wir haben emp: Partial<Employee>, können wir emp.idoder so, emp.nameaber wenn wir haben emp: Nullable<Employee>, können wir nichtemp.id
Yousuf Khan
1
Dies ist die eigentliche Antwort auf die Frage.
Patrick
36

Fügen Sie ?dem optionalen Feld einfach ein Fragezeichen hinzu .

interface Employee{
   id: number;
   name: string;
   salary?: number;
}
Miguel Ventura
quelle
54
Wie Ryan betonte ...? bedeutet optional in Typoskript, nicht nullbar. Ohne ? bedeutet, dass die Variable auf einen Wert gesetzt werden muss, der null oder undefiniert enthält. Mit? Sie können das ganze Deklarations-Ding überspringen.
Er Nrik
3
Danke dir! Ich habe nach "Typoskript optionaler Wert" gegoogelt, also ist dies genau das , wonach ich gesucht habe.
Fellow Stranger
13

Sie können einfach einen benutzerdefinierten Typ wie den folgenden implementieren:

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];
Willem van der Veen
quelle
10
type MyProps = {
  workoutType: string | null;
};
Ritwik
quelle
4

Ich hatte vor einiger Zeit die gleiche Frage. Alle Typen in ts sind nullbar, weil void ein Subtyp aller Typen ist (im Gegensatz zu zum Beispiel Scala).

Überprüfen Sie, ob dieses Flussdiagramm hilfreich ist - https://github.com/bcherny/language-types-comparison#typescript

Bcherny
quelle
2
-1: Das stimmt überhaupt nicht. Wie bei void‚Subtyp aller Art‘ (die Bodenart ), beziehen sich auf diesen Thread . Auch das Diagramm, das Sie für Scala bereitgestellt haben, ist falsch. Nothingin scala ist in der Tat der unterste Typ. Typescript, atm, hat keinen unteren Typ, während Scala dies tut .
Daniel Shin
2
"Subtyp aller Typen"! = Unterer Typ. Siehe die TS-Spezifikation hier github.com/Microsoft/TypeScript/blob/master/doc/…
bcherny
3

Ein nullbarer Typ kann einen Laufzeitfehler auslösen. Ich denke, es ist gut, eine Compiler-Option zu verwenden --strictNullChecksund number | nullals Typ zu deklarieren . Auch im Fall einer verschachtelten Funktion kann der Compiler nicht wissen, was er !beschädigen könnte, obwohl der Eingabetyp null ist. Daher empfehle ich die Verwendung (Ausrufezeichen).

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

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

Margaux
quelle