Необязательное сцепление для интерфейсов, имеющих подпись индекса - PullRequest
0 голосов
/ 01 апреля 2020

Я определил два интерфейса. У первого есть необязательное поле, у второго подпись индекса:

interface A {
  foo?: { bar: number };
}

interface B {
  [s: string]: { bar: number };
}

Почему первый интерфейс дает мне результат типа number | undefined, когда я получаю доступ к свойству с помощью необязательного связывания, тогда как второй дает только тип number?

const a: A = {};
const aa = a.foo?.bar;
// const aa: number | undefined

const b: B = {};
const bb = b.foo?.bar;
// const bb: number

1 Ответ

1 голос
/ 01 апреля 2020

Поскольку B индексируется как [s: string], считается, что любой допустимый строковый ключ приведет к доступу к значению { bar: number }. Так, с

const b: B = {};
const bb = b.foo?.bar;

он думает, что свойство foo всегда будет существовать - оно никогда не потерпит неудачу и превратится в undefined через необязательное сцепление.

В отличие от A :

interface A {
  foo?: { bar: number };
}

Поскольку свойство foo здесь не является обязательным, оно не обязательно существует (для Typescript), поэтому ?. может привести к тому, что свойство не будет найдено и undefined является результатом.

Вы можете дать понять, что не все свойства в B обязательно будут иметь объект bar, чередуя с undefined в типе значения объекта:

interface B {
  [s: string]: { bar: number } | undefined;
}

, в результате чего bb набирается как number | undefined.

...