Пример кода: создание насмешек в angular2

Я изучаю Angular2. На страницах DI есть пример кода для насмешек. https://angular.io/docs/ts/latest/guide/dependency-injection.html

Что это значит

let mockService = <HeroService> {getHeroes: () => expectedHeroes }

Похоже, определить mockService функция от HeroService функция.

Что такое <HeroService>? Является <HeroService> Кастинг?

let expectedHeroes = [{name: 'A'}, {name: 'B'}]
let mockService = <HeroService> {getHeroes: () => expectedHeroes }

it('should have heroes when HeroListComponent created', () => {
  let hlc = new HeroListComponent(mockService);
  expect(hlc.heroes.length).toEqual(expectedHeroes.length);
});

2 ответа

Решение

Добавить к ответу Дж. Б. Низета и дать небольшое объяснение причин, лежащих в основе кода.

TypeScript использует Структурную Систему Типов1. Это означает, что если он крякает как утка, то его можно считать уткой (или, точнее, совместимым с уткой). Возьмите например

class Duck {
  quack() { }
}

let duck = {
  quack: () => {}
}

поскольку duck имеет quack метод, вы можете передать его любому, что ожидает Duck, лайк

function doQuack(duck: Duck) {
  duck.quack();
}

doQuack(duck);

TypeScript достаточно умен, чтобы знать, что duck объектный литерал можно считать Duck даже если мы никогда не создадим экземпляр Duck с помощью duck = new Duck(), Это потому, что структура duck достаточно, чтобы быть совместимым с Duck тип, потому что это соответствует структуре; структура только одна quack метод.

Если бы мы попытались напечатать duck как Duckи у нас не было quack метод, то мы получили бы ошибку компиляции.

let duck: Duck = {   // compile error
  mooo: () => {}
};

let duck: Duck = {
  quack: () => {}    // OK
}

Как говорится, с вашим примером, HeroSerivce есть два метода, один, чтобы получить всех героев, и один, чтобы получить героя по идентификатору.

class HeroService {
  getHeroes(): Hero[] { .. }
  getHeroById(id: number): Hero { .. }
}

И HeroComponent с конструктором, который принимает HeroService

class HeroComponent {
  constructor(heroService: HeroService) {}
}

Теперь, если мы попытаемся передать следующее

let mockService = { getHeroes: () => expectedHeroes }

к HeroComponent конструктор, мы получим ошибку компиляции, потому что mockService не соответствует структуре HeroService, Он имеет только один getHeroes метод, когда структура на самом деле состоит из двух методов, getHeroes а также getHero,

Чтобы заставить компилятор просто принять его, мы "приводим" его к <HeroService>,

Мы могли бы передать следующее (без "приведения"), и это сработало бы, потому что оно соответствует структуре.

let mockService = {
  getHeroes: () => expectedHeroes,
  getHero: (id: number) => null
};

1 - Узнайте больше из главы документации TypeScript Совместимость типов

В JavaScript и TypeScript, {a: b} является литералом объекта. Он определил объект с одним свойством a имея значение b,

Так

{getHeroes: () => expectedHeroes }

это объект с одним свойством с именем getHeroesчье значение () => expectedHeroes() => expectedHeroes, Таким образом, значение является функцией без аргументов (()) и возвращая значение expectedHeroes,

<HeroService> называется утверждением типа:

Иногда вы окажетесь в ситуации, когда вы будете знать больше о значении, чем TypeScript. Обычно это происходит, когда вы знаете, что тип некоторого объекта может быть более конкретным, чем его текущий тип.

Утверждения типа - это способ сказать компилятору "доверяйте мне, я знаю, что я делаю". Утверждение типа похоже на приведение типов в других языках, но не выполняет никакой специальной проверки или реструктуризации данных. Он не влияет на время выполнения и используется исключительно компилятором.

Другие вопросы по тегам