Как объявить тип как обнуляемый в TypeScript?

249

У меня есть интерфейс в TypeScript.

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

Я хотел бы сделать salaryкак обнуляемое поле (как мы можем сделать в C #). Это возможно сделать в TypeScript?

Амитабх
источник

Ответы:

277

Все поля в JavaScript (и в TypeScript) могут иметь значение nullилиundefined .

Вы можете сделать поле необязательным, что отличается от нуля.

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

Сравнить с:

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
Похоже, что строго обнуляемые типы и строгие проверки на ноль были реализованы и поступят с Typescript 2.0! (или typescript@nextсейчас.)
mindplay.dk
ты уверен насчет var c в первом примере? Мне кажется, что var b и var c там одинаковы.
martinp999
Чтобы установить нулевое или неопределенное значение без ошибки компиляции, параметр tsconfig «строгий» должен быть удален или равен «ложь»"strict" : false
Николас Джанель
1
Это неверно JS различают нуль и неопределенный. Правильный код должен быть. salary:number|null;Если вы это сделаете, salary?:number; salary = null;вы получите ошибку. Однако salary = undefined;в этом случае все будет работать нормально. Решение: используйте Union т.е. '|'
Анкур Нигам
126

Тип соединения на мой взгляд - лучший вариант в этом случае:

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: Для этого , чтобы работать , как и ожидалось, вы должны включить strictNullChecksв tsconfig.

bjaksic
источник
9
Если вы используете --strictNullChecks (что и нужно), это верное решение. Я бы не стал использовать его в пользу необязательных членов, так как он заставляет вас добавлять явный нуль для всех литеральных объектов, но для возвращаемых значений функции это путь.
Geon
78

Чтобы быть более похожим на C # , определите Nullableтип следующим образом:

type Nullable<T> = T | null;

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

Бонус:

Чтобы Nullableповедение велось как встроенный тип Typescript, определите его в global.d.tsфайле определения в корневой папке источника. Этот путь работал для меня:/src/global.d.ts

Тим Сантефорд
источник
1
Мой любимый ответ - прямо отвечает на вопрос, не читая в него.
Lqueryvg
1
Использование этого нарушает автоматическое заполнение свойств объекта. Например, если у нас есть emp: Partial<Employee>, мы можем сделать emp.idили emp.nameт. Д., Но если у нас есть emp: Nullable<Employee>, мы не можемemp.id
Юсуф Хан
1
Это фактический ответ на вопрос.
Патрик
39

Просто добавьте знак вопроса ?в дополнительное поле.

interface Employee{
   id: number;
   name: string;
   salary?: number;
}
Мигель Вентура
источник
54
Как указал Райан ...? означает необязательный в машинописи, не обнуляемый. Без? означает, что переменная должна быть установлена ​​в значение, включая ноль или неопределенное. С участием ? Вы можете пропустить всю декларацию.
Он Нрик
3
Спасибо! Я погуглил «необязательное значение машинописи», так что это именно то , что я искал.
Товарищ незнакомец
13

Вы можете просто реализовать определяемый пользователем тип, как показано ниже:

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

У меня был тот же вопрос некоторое время назад .. все типы в ts обнуляются, потому что void является подтипом всех типов (в отличие, например, от scala).

посмотрите, помогает ли эта блок-схема - https://github.com/bcherny/language-types-comparison#typescript

bcherny
источник
2
-1: Это совсем не так. Что касается void«подтипа всех типов» ( нижний тип ), обратитесь к этой теме . Диаграмма, которую вы указали для scala, также неверна. Nothingв Scala, на самом деле, нижний тип. Typescript, atm, не имеет нижнего типа, в то время как scala имеет .
Даниэль Шин
2
«Подтип всех типов»! = Нижний тип. Смотрите спецификацию TS здесь github.com/Microsoft/TypeScript/blob/master/doc/…
bcherny
3

Обнуляемый тип может вызвать ошибку во время выполнения. Поэтому я думаю, что хорошо использовать опцию компилятора --strictNullChecksи объявить number | nullкак тип. также в случае вложенной функции, хотя тип ввода равен нулю, компилятор не может знать, что он может сломать, поэтому я рекомендую использовать !(восклицательный знак).

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

Ссылка. https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-type-assertions

Margaux
источник