Typescript 键入泛型并将其定义为可选

Typescript 键入泛型并将其定义为可选,typescript,Typescript,我有一个接受泛型的类 interface Converter<T = Buffer> { uuid: string; decode?: (value: Buffer) => T; encode?: (value: T) => Buffer; } type Converters = Record<string, Converter<any>>; export default class Service<C extends Con

我有一个接受泛型的类

interface Converter<T = Buffer> {
  uuid: string;
  decode?: (value: Buffer) => T;
  encode?: (value: T) => Buffer;
}

type Converters = Record<string, Converter<any>>;

export default class Service<C extends Converters> {
  private converters?: Converters;

  constructor(converters?: C) {
    this.converters = converters;
  }
}
这个

因为转换器是可选的

现在的问题是
服务
类有一个名为
读取
的方法,该方法将接受一个名为
名称
的参数并返回一个值,
名称
的类型和返回类型应基于此

  • 哪些转换器已传递到
    服务
  • 如果任何转换器已传递到
    服务
如果已提供转换器

  • read应仅接受转换器的键作为
    名称
    参数
  • read应返回与该名称对应的转换器的泛型类型
如果未传递任何转换器,
read
应接受任何字符串作为参数并返回缓冲区

所以如果我通过

const converters = {
  manufacturer: {
    uuid: "2a29",
    decode: (buffer: Buffer) => buffer.toString()
  },
  model: {
    uuid: "2a24",
    decode: (buffer: Buffer) => buffer.readInt8(0)
  }
}

const service = new Service(converters);
const serviceNoConverter = new Service();
这应该发生

const value = service.read("manufacturer");
//    ^^^^^ type string

const value = service.read("model");
//    ^^^^^ type number

const value = service.read("aassd");
//                          ^^^^^ type error, not manufacturer or model

const value = serviceNoConverter.read("asdasdasd")
//    ^^^^^ type Buffer                ^^^^^^^^^ any string is allowed
因此,在StackOverflow的帮助下(特别是在jcalz的帮助下,谢谢老兄),我做到了这一点:


我认为将
C
约束为
转换器|未定义的
未定义的
作为默认值应该有效。我还建议将成员变量更改为
C
类型,因为它已被正确约束:

类服务{
专用转换器?:C;
构造函数(转换器?:C){
这个。转换器=转换器;
}
//...
}
这里的关键是,通过将默认值设置为
undefined
,创建没有转换器的服务将导致类型:
service
,而不是
service


我认为将
C
约束为
转换器|未定义
未定义
作为默认值应该有效。我还建议将成员变量更改为
C
类型,因为它已被正确约束:

类服务{
专用转换器?:C;
构造函数(转换器?:C){
这个。转换器=转换器;
}
//...
}
这里的关键是,通过将默认值设置为
undefined
,创建没有转换器的服务将导致类型:
service
,而不是
service

操场上最初的问题是: -过度复杂化。 -
转换器
属性类型

正如卢卡斯盖特所指出的,
转换器应为C型。
但是,
undefined
的默认通用值不是必需的。 它也可以像这样工作:

...
class Service<C extends Converters> {
  private converters?: C;

  constructor(converters?: C) {
    this.converters = converters;
  }

  public read<N extends keyof C>(name: N): C[N] {
      ...
  }
}
。。。
班级服务{
专用转换器?:C;
构造函数(转换器?:C){
这个。转换器=转换器;
}
公开阅读(名称:N):C[N]{
...
}
}

操场上最初的问题是: -过度复杂化。 -
转换器
属性类型

正如卢卡斯盖特所指出的,
转换器应为C型。
但是,
undefined
的默认通用值不是必需的。 它也可以像这样工作:

...
class Service<C extends Converters> {
  private converters?: C;

  constructor(converters?: C) {
    this.converters = converters;
  }

  public read<N extends keyof C>(name: N): C[N] {
      ...
  }
}
。。。
班级服务{
专用转换器?:C;
构造函数(转换器?:C){
这个。转换器=转换器;
}
公开阅读(名称:N):C[N]{
...
}
}

Hey@Alexey,谢谢你,但是如果你这样做,当没有转换器被传递到服务时,你会得到任何作为返回类型Hey@Alexey,谢谢,但是如果你这样做,当没有转换器被传递到服务时,你会得到任何作为返回类型
const converters = {
  manufacturer: {
    uuid: "2a29",
    decode: (buffer: Buffer) => buffer.toString()
  },
  model: {
    uuid: "2a24",
    decode: (buffer: Buffer) => buffer.readInt8(0)
  }
}

const service = new Service(converters);
const serviceNoConverter = new Service();
const value = service.read("manufacturer");
//    ^^^^^ type string

const value = service.read("model");
//    ^^^^^ type number

const value = service.read("aassd");
//                          ^^^^^ type error, not manufacturer or model

const value = serviceNoConverter.read("asdasdasd")
//    ^^^^^ type Buffer                ^^^^^^^^^ any string is allowed
...
class Service<C extends Converters> {
  private converters?: C;

  constructor(converters?: C) {
    this.converters = converters;
  }

  public read<N extends keyof C>(name: N): C[N] {
      ...
  }
}