Есть ли способ в TypeScript использовать интерфейс в качестве защиты, не теряя при этом специфику объекта? - PullRequest
0 голосов
/ 15 февраля 2019

У меня есть проблема, когда я пытаюсь создать интерфейс для общих модулей в TypeScript, который для целей этого вопроса предположим, имеет следующую форму:

interface A {
  x: string;
  y: { [name: string]: (...args: any) => {type: string; payload?: any} };
  z?: () => any
}

Цель этого интерфейса - два-fold:

  1. Для человека, производящего модуль, я хочу, чтобы он мог знать, что то, что он создает, соответствует A.
  2. Для человека, потребляющего модуль,Я хочу, чтобы они могли иметь максимально возможную типизацию.

Например, если бы у меня было:

const bar = {
  x: 'hello',
  y: { 'world': (a: string, b: number) => ({ type: a, payload: b}) }
}

Обратите внимание на отсутствие ссылки на интерфейс A.

Если бы я потом набрал: bar. Я бы понял, что у него есть свойства x и y.Более того, после ввода bar.y. мне будет предложено указать, что существует world и тип функции, связанный с ним.

Однако, если я добавлю A:

const bar: A = {
  x: 'hello',
  y: { 'world': (a: string, b: number) => ({ type: a, payload: b}) }
}

это помогает в случае, если кто-то случайно добавил неправильное свойство, такое как:

const bar: A = {
  iDontBelong: true, // wrong
  x: 'hello',
  y: { 'world': (a: string, b: number) => ({ type: a, payload: b}) }
}

или даже

const bar: A = {
  x: 5, // wrong
  y: { 'world': (a: string, b: number) => ({ type: a, payload: b}) }
}

Теперь проблема заключается в том, что если кто-то импортирует bar и наберет bar. они будут получать предложения, которые непосредственно для интерфейса A.Он теряет знание о том, что bar имеет только x и y (и не z), а также теряет информацию о специфическом типе y, означающем, что он даже не знает, что world существуетна y.

Есть ли способ заставить обе эти вещи существовать одновременно?

1 Ответ

0 голосов
/ 15 февраля 2019

Есть ли способ заставить обе эти вещи существовать одновременно

Как только вы скажете : A, тогда вы не получитеintellisense для вещей в сумке с предметами ([name: string]).

Этого можно избежать, не аннотируя , а выполнив проверку типа, например:

const bar = {
  x: 'hello',
  y: { 'world': (a: string, b: number) => ({ type: a, payload: b}) }
}
const _ensureA: A = bar; // Type test 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...