繁体   English   中英

Typescript 泛型条件类型

[英]Typescript generic conditional types

我怎样才能在没有任何情况下修复这些类型?

class Selections<V, T extends boolean = false> {
  /** Cache for the array value of the selected items. */
  private _selected: (T extends true ? V[] : V) | null;

  constructor(private multiple: T = false) {}
  // Type 'boolean' is not assignable to type 'T'.
  //   'boolean' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'boolean'.ts(2322)

  get selected(): T extends true ? V[] : V {
    if (!this._selected) {
      // this is for example
      const value: V = {} as V;

      // Type 'V[]' is not assignable to type 'T extends true ? V[] : V'.ts(2322)
      // (property) Selections<V, T extends boolean = true>._selected: T extends true ? V[] : V
      if (this.multiple) this._selected = [value];
      // Type 'V[]' is not assignable to type 'T extends true ? V[] : V'.ts(2322)
      // (property) Selections<V, T extends boolean = true>._selected: T extends true ? V[] : V
      else this._selected = value;

      // Type 'V[]' is not assignable to type 'T extends true ? V[] : V'.ts(2322)
      // (property) Selections<V, T extends boolean = true>._selected: T extends true ? V[] : V
      this._selected = this.multiple ? [value] : value;
    }

    return this._selected;
  }
}

const testTrue = new Selections<string, true>(true);
testTrue.selected; // is ok (property) Selections<string, true>.selected: string[]

const testFalse = new Selections<string, false>(false);
testFalse.selected; // is ok (property) Selections<string, true>.selected: string

const testEmpty = new Selections<string>();
testEmpty.selected; // is ok (property) Selections<string, true>.selected: string

这种行为几乎是意料之中的,因为您的扩展类型boolean ,您没有将其限制为truefalse 不幸的是 TypeScript 没有提供任何限制泛型类型的东西,所以现在没有解决您的问题的方法。

我唯一能想到的是创建一个工厂 static 重载方法,这将提供您想要的行为。

class Selections<V, T extends boolean> {
  private _selected: (T extends true ? V[] : V) | null;

  constructor(private multiple?: T) {}

  get selected(): T extends true ? V[] : V {
    if (!this._selected) {
      const value: V = {} as V;

      if (this.multiple) (this._selected as V[]) = [value];
      else (this._selected as V) = value;
    }

    return this._selected as T extends true ? V[] : V;
  }

  public static create<Vs>(): Selections<Vs, false>;
  public static create<Vs>(val: true): Selections<Vs, true>;
  public static create<Vs>(val: false): Selections<Vs, false>;

  public static create<Vs>(val: boolean = false): Selections<Vs, boolean> {
    return new Selections<Vs,boolean>(val);
  }
}

const testTrue = Selections.create<string>(true);
testTrue.selected; // Selections<string, true>.selected: string[]

const testFalse = Selections.create<string>(false);
testFalse.selected; // Selections<string, true>.selected: string

const testEmpty = Selections.create<string>();
testEmpty.selected; // Selections<string, true>.selected: string

暂无
暂无

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

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