Решение для ошибки
Похоже, ошибка в вашей службе
import profile from '../../../shared/utils/client-profile.json';
import { ClientProfile } from '../models/client-profile.model';
export class ClientProfileService {
public profile: ClientProfile;
constructor() {}
getClientProfile(): ClientProfile {
return profile; // <- this is the profile you loaded from the .json file
// so it does not have `.deserialize()` which is where the error is coming from
}
}
Если вы хотите вернуть профиль службы, вам нужно this.profile
, но, похоже, вам сначала нужно сопоставить этот объект, чтобы не получить ошибку времени выполнения.
import profile from '../../../shared/utils/client-profile.json';
import { ClientProfile } from '../models/client-profile.model';
export class ClientProfileService {
public profile: ClientProfile;
constructor() {
// create a new ClientProfile from the loaded .json file
// JSON.parse() may not be necessary
this.profile = new ClientProfile().deserialize(JSON.parse(profile));
}
getClientProfile(): ClientProfile {
return this.profile; // <- change to `this.profile`
}
}
Это должно сработать (или, по крайней мере, приблизить вас).
Практика моделирования
Когда дело доходит до моделирования в Typescript, лучшим решением (IMO) является использование interfaces
для определения ваших "POJO" (Plain Old JavaScript Objects). Причина в том, что при загрузке данных из бэкэнда ваш http-клиент преобразует ответ в объект JavaScript за кулисами. Это также избавит вас от необходимости беспокоиться о создании классов new
повсюду.
Для вашего конкретного сценария я бы применил это изменение следующим образом:
пример структуры папок (ПРИМЕЧАНИЕ. Мне нравится хранить мои службы в отдельной папке так как они обычно предоставляются в root
)
.
├── src
└── app
├── ...
├── services
│ └── client-profile.service.ts
├── client-profile
│ ├── client-profile.component.html
│ └── client-profile.component.ts
└── models
└── client-profile.model.ts
client-profile.model.ts
/* I like to prefix my interface delcarations with an `I` */
export interface IClientProfile {
isPayrollAdmin: boolean;
contacts: IContact[];
}
export interface IContact {
name: string;
phone: string;
phoneExt: number;
email: string;
implementationRole: boolean;
operationsRole: boolean;
userId: number;
}
Тогда вы просто скажете машинописи, что тип объекта, который вы ожидаете, и он будет использовать ваше определение. Так что в вашем client-profile.service.ts
вам не нужно будет создавать новый класс.
client-profile.service.ts
import profile from '../../../shared/utils/client-profile.json';
import { IClientProfile } from '../models/client-profile.model';
export class ClientProfileService {
public profile: IClientProfile;
constructor() {
// you don't need to create a new object because you already have a JavaScript object
// you just need to tell typescript what kind of object you have
this.profile = JSON.parse(profile) as IClientProfile;
}
getClientProfile(): IClientProfile {
return this.profile;
}
}
Когда вы приступите к выполнению http-запросов на данные, вам не придется делать никаких дополнительных сопоставлений с построить дополнительные объекты.
client-profile.service.ts пример реализации http
import { HttpClient } from '@angular/common/http';
import profile from '../../../shared/utils/client-profile.json';
import { IClientProfile } from '../models/client-profile.model';
export class ClientProfileService {
public profile: IClientProfile;
constructor(private http: HttpClient) { /* ... */ }
/** example http request where you tell typescript what kind of object you are expecting */
loadAllProfiles(): Observable<IClientProfile[]> {
return this.http.get<IClientProfile[]>('api/profiles');
}
// ...
}
Старайтесь избегать создания или добавления методов к данным, которые вы получаете от бэкэнд Вы хотите, чтобы ваши модели данных были максимально чистыми.