Comment déclarer un type comme nullable dans TypeScript?

249

J'ai une interface en TypeScript.

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

Je voudrais faire salaryun champ nullable (comme on peut le faire en C #). Est-ce possible de faire en TypeScript?

Amitabh
la source

Réponses:

277

Tous les champs en JavaScript (et en TypeScript) peuvent avoir la valeur nullou undefined.

Vous pouvez rendre le champ facultatif, différent de 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;
}

Comparer avec:

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
la source
35
On dirait que des types strictement nullables et des vérifications nulles strictes ont été implémentés et arriveront avec Typescript 2.0! (ou typescript@nextmaintenant.)
mindplay.dk
êtes-vous sûr de var c dans le premier exemple? Il me semble que var b et var c sont les mêmes là-bas.
martinp999
Afin de définir une valeur nulle ou non définie sans erreur de compilation, l'option "stricte" de tsconfig doit être supprimée ou égale à "false""strict" : false
Nicolas Janel
1
Ceci est une erreur. JS fait la distinction entre null et indéfini. Le code correct devrait être salary:number|null;Si vous le faites, salary?:number; salary = null;vous obtiendrez une erreur. Cependant, salary = undefined;cela fonctionnera très bien dans ce cas. Solution: utilisez Union ie '|'
Ankur Nigam
126

Le type d'union est dans mon esprit la meilleure option dans ce cas:

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: Pour que cela fonctionne comme prévu, vous devez activer l' strictNullChecksen tsconfig.

bjaksic
la source
9
Si vous utilisez --strictNullChecks (ce que vous devriez), c'est une solution valide. Je ne l'utiliserais pas en faveur des membres facultatifs, car cela vous oblige à ajouter un null explicite sur tous les objets littéraux, mais pour les valeurs de retour de fonction, c'est la voie à suivre.
geon
78

Pour ressembler davantage à C # , définissez le Nullabletype comme ceci:

type Nullable<T> = T | null;

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

Prime:

Pour vous Nullablecomporter comme un type Typescript intégré, définissez-le dans un global.d.tsfichier de définition dans le dossier source racine. Ce chemin a fonctionné pour moi:/src/global.d.ts

Tim Santeford
la source
1
Ma réponse préférée - répond directement à la question sans y lire.
Lqueryvg
1
Son utilisation interrompt l'auto-complétion des propriétés de l'objet. Par exemple, si nous avons emp: Partial<Employee>, nous pouvons faire emp.idou emp.nameetc., mais si nous avons emp: Nullable<Employee>, nous ne pouvons pas faireemp.id
Yousuf Khan
1
C'est la vraie réponse à la question.
Patrick
39

Ajoutez simplement un point d'interrogation ?au champ facultatif.

interface Employee{
   id: number;
   name: string;
   salary?: number;
}
Miguel Ventura
la source
54
Comme Ryan l'a souligné ...? signifie facultatif en tapuscrit, non nullable. Sans pour autant ? signifie que la var doit être définie sur une valeur incluant null ou indéfini. Avec ? vous pouvez ignorer tout le truc de déclaration.
He Nrik le
3
Je vous remercie! J'ai googlé pour "valeur facultative dactylographiée" donc c'est exactement ce que je cherchais.
Fellow Stranger
13

Vous pouvez simplement implémenter un type défini par l'utilisateur comme le suivant:

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
la source
10
type MyProps = {
  workoutType: string | null;
};
Ritwik
la source
4

j'ai eu cette même question il y a quelque temps .. tous les types de ts sont nullables, car void est un sous-type de tous les types (contrairement, par exemple, scala).

voir si cet organigramme aide - https://github.com/bcherny/language-types-comparison#typescript

bcherny
la source
2
-1: Ce n'est pas vrai du tout. Quant à voidêtre «sous-type de tous les types» ( type inférieur ), reportez-vous à ce fil . Le tableau que vous avez fourni pour scala est également incorrect. Nothingen scala est, en fait, le type inférieur. Tapuscrit, atm, ne pas avoir le type de fond tout scala fait .
Daniel Shin
2
"Sous-type de tous types"! = Type inférieur. Voir la spécification TS ici github.com/Microsoft/TypeScript/blob/master/doc/…
bcherny
3

Un type nul peut invoquer une erreur d'exécution. Je pense donc qu'il est bon d'utiliser une option de compilation --strictNullCheckset de déclarer number | nullcomme type. également en cas de fonction imbriquée, bien que le type d'entrée soit nul, le compilateur ne peut pas savoir ce qu'il pourrait casser, donc je recommande l'utilisation !(marque d'exclamination).

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

Référence. https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-type-assertions

Margaux
la source