递归函数的键入

丹尼尔·拉莫斯(Daniel Ramos)

我正在尝试编写一个unwrap具有值的类方法,或带有内部值的自身实例:

class Identity<T> {
  private readonly value: T;

  constructor(value: T) {
    this.value = value;
  }

  static of<T>(value: T): Identity<T> {
    return new Identity(value);
  }

  join(): T { // which return type should go here?
    if (this.value instanceof Identity) {
      return this.value.join();
    }

    return this.value;
  }
}

这是测试:

const one = Identity.of(Identity.of(Identity.of(123)));
const result: number = one.join();
expect(result).toEqual(123);

谢谢大家!

沙伯

您可以更改type参数T,使其始终是完全嵌套的类型:

class Identity<T> {
  private readonly value: T | Identity<T>;

  constructor(value: Identity<T>);
  constructor(value: T);

  constructor(value: any) {
    this.value = value;
  }

  static of<T>(value: Identity<T>): Identity<T>;
  static of<T>(valud: T): Identity<T>;
  static of<T>(value: T | Identity<T>) {
    return new Identity(value);
  }

  join(): T {
    if (this.value instanceof Identity) {
      return this.value.join();
    }
    return this.value;
  }
}

const one = Identity.of(Identity.of(Identity.of(123)));
const result: number = one.join();

const result2 = new Identity(new Identity(new Identity(321)));
// Identity<number>

我建议使用上述方法,因为它似乎提供了您真正想要的功能。

如果您T实际上需要嵌套该类型Identity<Identity<...>>则仍然可以,如果value已公开,则可以执行以下操作:

class Identity<T> {
  public readonly value: T;

  constructor(value: T) {
    this.value = value;
  }

  static of<T>(value: T): Identity<T> {
    return new Identity(value);
  }

  public join(): IdentityJoinResult<T> {
    if (this.value instanceof Identity) {
      return this.value.join();
    }

    return this.value as IdentityJoinResult<T>;
  }
}

type IdentityJoinResult<T> = 
  T extends Identity<any>
    ? { [Key in keyof T]: IdentityJoinResult<T[Key]> }["value"]
    : T
;

const one = Identity.of(Identity.of(Identity.of(123)));
const result: number = one.join();

const result2 = new Identity(new Identity(new Identity(321))).join();

但是,如果更改value为私有,您会注意到您不再能够在类型签名中按“值”进行索引,因此,我们要解决的最后一件事是将类型逻辑推迟到单独的公共接口上,可以从类型确定:

class Identity<T> {
  private readonly value: T;

  constructor(value: T) {
    this.value = value;
  }

  static of<T>(value: T): Identity<T> {
    return new Identity(value);
  }

  public join(): IdentityJoinResult<T> {
    if (this.value instanceof Identity) {
      return this.value.join();
    }

    return this.value as IdentityJoinResult<T>;
  }
}

interface NestedIdentity<T> {
  _value: T extends Identity<infer U> ? NestedIdentity<U> : T;
}

type NestedIdentityValue<T> = 
  T extends NestedIdentity<any>
    ? { [Key in keyof T]: NestedIdentityValue<T[Key]> }["_value"]
    : T
;

type IdentityJoinResult<T> = NestedIdentityValue<NestedIdentity<T>>;

const one = Identity.of(Identity.of(Identity.of(123)));
const result: number = one.join();
const result2 = new Identity(new Identity(new Identity(321))).join();

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章