Параметр функции, который реализует интерфейс или расширение интерфейса - PullRequest
0 голосов
/ 11 марта 2020

У меня есть следующий код:

interface IFoo {
  foo: string;
}

interface IFooBar extends IFoo {
  bar: string;
}

const myFun = (fooOrFooBar: IFoo) => {
  console.log(fooOrFooBar.foo);
  console.log(fooOrFooBar.bar || "I do not have bar.");
}

const myFoo: IFoo = {
  foo: "Hello",
}

const myFooBar: IFooBar = {
  foo: "Hello",
  bar: "World!",
}

myFun(myFoo);
myFun(myFooBar);

Это позволило бы мне передавать объектам в эту функцию, которые либо реализуют IFoo, либо расширение IFoo, и работать с ними по-разному. Однако приведенный выше код не компилируется как Property 'bar' does not exist on type 'IFoo'. Есть ли способ определить функцию так, чтобы она принимала аргумент, который либо реализует IFoo, либо любой интерфейс, который расширяет IFoo?

1 Ответ

0 голосов
/ 11 марта 2020

Вы можете использовать дженерики, если вы действительно хотите принять что-либо, что расширяет IFoo, например:

const has = <K extends string>(
  key: K,
  x: object,
): x is { [key in K]: unknown } => (
  key in x
);

const myFun = <T extends IFoo>(fooOrFooBar: T) => {
  console.log(fooOrFooBar.foo);
  console.log(has('bar', fooOrFooBar) ? fooOrFooBar.bar : "I do not have bar.");
}

Типографский щит has может использоваться для безопасного доступа к любому свойству, для которого вы можете проверить .

Однако, если вы уже ожидаете, что свойство bar будет частью объекта, вы также можете указать это в сигнатуре типа без обобщения:

const myFun = (fooOrFooBar: IFoo | IFooBar) => {
  console.log(fooOrFooBar.foo);
  console.log('bar' in fooOrFooBar ? fooOrFooBar.bar : "I do not have bar.");
}

Это все еще позволяет передавать все, что расширяет IFoo:

const x = { foo: "fsd", x: 'sdf'}
myFun(x);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...