Типизированный объектный литерал с вложенными свойствами не может заставить работать intellisense - PullRequest
0 голосов
/ 03 мая 2020

Я пытаюсь улучшить свой проект с помощью машинописного текста, и я не могу понять, как заставить работать следующее:

Скажем, что у меня есть выражение функции, столь же простое, как это

const foo = (objectLiteral: any): void => {
  console.log(objectLiteral)
}

Теперь я просто собираюсь использовать его следующим образом.

foo({
  name: 'guybrush',
  nestedProperties: {
    gunPowderAmount: 1
  },
  speak () {
    // First issue, "this" is any type. I don't get any intellisense for the properties 
    // within the object.
    // this.
  }
})

Как видно из моего комментария внутри функции говорить, "this" имеет любой тип, и я не могу получить доступ ни к одному из свойства объекта. Я считаю, что это связано с этим https://github.com/microsoft/TypeScript/issues/11072.

Я знаю, что это не связано с машинописью - пока - я туда добираюсь.

Тогда я предположил, что, поскольку я использую машинопись, я могу использовать типы , прохладно! И поэтому мой код видоизменился следующим образом:

type MappedCharacter = {
  name: string;
  speak: () => void;
  nestedProperties: { [key: string]: number | string };
}

const foo2 = (objectLiteral: MappedCharacter) => {
  console.log(objectLiteral)
}

И я собираюсь использовать его так:

foo2({
  name: 'guybrush',
  nestedProperties: {
    gunPowderAmount: 1
  },
  speak () {
    // Second issue. Now "this" has access to the properties, but NOT
    // the one which are NESTED into "nestedProperties"
  }
})

Круто, у меня теперь есть доступ к «этому», и Я могу настроить свойства «name» и «nestedProperties».

Но у "nestedProperties" есть и другие свойства! Где они?

Заключительный тест, я собираюсь избавиться от выражения функции и просто протестировать объект самостоятельно.

const objectLiteral: MappedCharacter = {
  name: 'guybrush',
  nestedProperties: {
    gunPowderAmount: 1
  },
  speak () {
    // Third issue. Even if not used in a function, "this.nestedProperties" can't dig any 
    // deeper.
    // this.nestedProperties.
  }
}

Начиная с комментария в речи Функция, опять же, мне не повезло, чтобы это вложенное свойство заработало.

То, что я тоже безуспешно пытался, это изменение моего типа на:

type MappedCharacter = {
  name: string;
  speak: () => void;
  nestedProperties: keyof MappedCharacter['nestedProperties'];
}


Что приводит к 'nestedProperties' прямо или косвенно ссылается на собственную аннотацию типа

РЕДАКТИРОВАТЬ: я не хочу определять тип для объекта "nestedProperties". Я просто хочу, чтобы он был как можно более обобщенным c, потому что я не могу предвидеть, какие свойства он может содержать.

EDIT2: Если у меня есть обычный литерал объекта, без каких-либо наборов, vscode МОЖЕТ определить эти свойства как можно более вложенными. Я хочу добиться одинакового поведения с типами. Я обычно использую Vuejs для своих проектов с расширением Vetur, и когда я определяю различные свойства для своей функции данных, intellisense просто работает.

Может кто-нибудь пролить свет на эту проблему? Какая недостающая часть головоломки?

1 Ответ

0 голосов
/ 03 мая 2020

Когда вы определяете тип MappedCharacter, вы в основном говорите, что nestedProperties имеет некоторые свойства. Вы не определяете, какой, поэтому компилятор не имеет этой информации.

Затем вы создаете objectLiteral объект, где nestedProperties имеет свойство gunPowderAmount - но это только для этого конкретного объекта, и в этот конкретный момент времени. Функция speak() все еще проверяется на соответствие типу MappedCharacter, для которого до сих пор не определено свойство gunPowderAmount.

Я бы посоветовал, если вы знаете, какие различные свойства будут отличаться MappedCharacter ' s, определите это следующим образом:

type MappedCharacter<TProps> = {
  name: string;
  speak: () => void;
  nestedProperties: TProps
}

type GuybrushProps = {
  gunPowderAmount: number
}

const objectLiteral: MappedCharacter<GuybrushProps> = {
  name: 'guybrush',
  nestedProperties: {
    gunPowderAmount: 1
  },
  speak () {
    // Then, intellisense here should work as you expect it to
  }
}
...