【问题标题】:Mapped types: remove private interface映射类型:移除私有接口
【发布时间】:2020-06-08 21:19:19
【问题描述】:

在 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 来解决这个问题,该接口描述了 HttpClient 的公共接口,并直接使用它而不是类类型,但这是很多工作,需要保留手动同步。

有没有办法使用映射类型从类型中删除所有非公共属性?

类似:

type PublicInterface<T> = {
    [P in PublicNames<T>]: T[P];
}

所以它可以用在你不关心隐私的地方:

class MyService {
  constructor(private http: PublicInterface<HttpClient>) {
  }
  // Implementation
}

【问题讨论】:

    标签: typescript mapped-types


    【解决方案1】:

    keyof 足够聪明,只能偷看公钥:

    class Person {
      constructor(private name: string, public age: number) { }
    }
    
    type PublicInterface<T> = {
        [P in keyof T]: T[P];
    }
    
    const p: PublicInterface<Person> = { age: 42 }; // no error
    

    Playground


    使用Pick 实用程序甚至更短(结果等同于上述映射类型):

    type PublicInterface<T> = Pick<T, keyof T>;
    

    Playground

    【讨论】:

    • 多年来我一直在使用 typescript 和映射类型,现在才注意到这种行为 ?‍♂️ 非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-03
    • 2023-03-28
    • 2019-12-06
    • 2020-11-29
    • 2021-08-15
    • 2021-05-15
    • 2018-11-28
    相关资源
    最近更新 更多