简体   繁体   English

TypeScript 类型安全服务注册表

[英]TypeScript type-safe service registry

How can I create a type-safe service registry in Typescript.如何在 Typescript 中创建类型安全的服务注册表。 Basically, a function that returns a concrete type based on the argument.基本上,一个 function 根据参数返回一个具体类型。

get("a") would return an object of type ServiceA.
get("b") would return an object of type ServiceB.

I followed the answer from here: https://stackoverflow.com/a/47098963/12116498 but am still getting typing errors.我从这里得到了答案: https://stackoverflow.com/a/47098963/12116498但我仍然遇到打字错误。

I have reduced my problem to the following and added the type errors I am getting:我已将我的问题减少到以下内容,并添加了我得到的类型错误:

console.log("Test get");
console.log("Get foo from AlertsService:", get('AlertsService').foo);
console.log("Get foo from AlertsService:", get('ModalService').foo);
console.log("Get foo from AlertsService:", get('ModalService').bar);
 
function get<T extends keyof ServiceMapping>(serviceType: T): ServiceMapping[T] {
  const t: keyof ServiceMapping = serviceType;
 
  switch (t) {
    case 'AlertsService':
 
// TS2322: Type '{ type: "AlertsService"; foo: string; }' is not assignable to type 'ServiceMapping[T]'.
// Type '{ type: "AlertsService"; foo: string; }' is not assignable to type 'never'.
// The intersection 'AlertsService & ModalService' was reduced to 'never' because property 'type' has conflicting types in some constituents.
 
      return {
        type: 'AlertsService',
        foo: 'testing'
      };
    case 'ModalService':
     
// TS2322: Type '{ type: "ModalService"; foo: string; bar: string; }' is not assignable to type 'ServiceMapping[T]'.
// Type '{ type: "ModalService"; foo: string; bar: string; }' is not assignable to type 'never'.
// The intersection 'AlertsService & ModalService' was reduced to 'never' because property 'type' has conflicting types in some constituents.
     
      return {
        type: 'ModalService',
        foo: 'testing',
        bar: 'bar test'
      };
 
    default:
      throw new Error("nope");
  }
}
 
export type ServiceMapping = {
  AlertsService: AlertsService;
  ModalService: ModalService;
}
 
export type AlertsService = {
  type: 'AlertsService',
  foo: string
}
 
export type ModalService = {
  type: 'ModalService',
  foo: string,
  bar: string
}

It is important to have the return type be narrowly scoped and not a union of other types.返回类型的范围很窄,而不是其他类型的联合,这一点很重要。

@kruschid please tell me why overloadings are bad @kruschid 请告诉我为什么重载不好


  type AlertsService = {
    type: 'AlertsService',
    foo: string,
  }

  type ModalService = {
    type: 'ModalService',
    foo: string,
    bar: string
  }

  function get<T extends 'AlertsService'>(arg: 'AlertsService'): AlertsService
  function get<T extends 'ModalService'>(arg: T): ModalService
  function get<T extends 'AlertsService' | 'ModalService'>(arg: T) {

    switch (arg) {
      case 'AlertsService':
        return {
          type: 'AlertsService',
          foo: 'testing'
        };
      case 'ModalService':
        return {
          type: 'ModalService',
          foo: 'testing',
          bar: 'bar test'
        };

      default:
        throw new Error("nope");
    }
  }


  const result = get('AlertsService') // AlertsService
  const result2 = get('ModalService') // ModalService

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM