В TypeScript закрытые атрибуты считаются частью формы (или интерфейса) типа.
class Person {
constructor(private name: string, public age: number) { }
}
const p: Person = { age: 42 };
// Error: Property 'name' is missing.
Это допустимо, поскольку TypeScript должен отслеживать личные данные.
class Person {
constructor(private name: string, public age: number) { }
equals(other: Person) {
return this.name === other.name && this.age === other.age;
// This is valid, because TypeScript kept track of the private `name` property!
}
}
Однако обычно вы хотите игнорировать закрытый интерфейс. Например, когда вы используете внедрение зависимостей и модульное тестирование.
class HttpClient {
constructor(private log: Logger) {
}
async doGet(url: string) {
return (await fetch(url)).json();
}
}
class MyService {
constructor(private http: HttpClient) {
}
// Implementation
}
// Unit test for MyService:
describe('MyService', () => {
it('should work', () => {
const httpMock: HttpClient = { // ERROR: Property 'log' is missing
doGet(url: string) {
return Promise.resolve({ name: 'Han' });
}
};
const sut = new MyService(httpMock);
});
});
Я знаю, что мы могли бы решить эту проблему, добавив интерфейс IHttpClient
, который описывает интерфейс publi c для HttpClient
и используйте это вместо типа класса напрямую, но это большая работа, и ее нужно держать в syn c вручную.
Есть ли способ удалить все неопубликованные свойства c из типа, использующего сопоставленный тип?
Что-то вроде:
type PublicInterface<T> = {
[P in PublicNames<T>]: T[P];
}
Так что это может быть используется в местах, где вы не заботитесь о рядовых:
class MyService {
constructor(private http: PublicInterface<HttpClient>) {
}
// Implementation
}