Пример кода: создание насмешек в 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. Обычно это происходит, когда вы знаете, что тип некоторого объекта может быть более конкретным, чем его текущий тип.
Утверждения типа - это способ сказать компилятору "доверяйте мне, я знаю, что я делаю". Утверждение типа похоже на приведение типов в других языках, но не выполняет никакой специальной проверки или реструктуризации данных. Он не влияет на время выполнения и используется исключительно компилятором.