【问题标题】:Typescript Array.isArray guard statement and return types on functionTypescript Array.isArray 保护语句和函数返回类型
【发布时间】:2021-03-26 06:25:01
【问题描述】:

我有以下函数按预期工作,如果将数组传递给第二个参数,则返回类型被正确键入为泛型 T 的数组。

type V<M, T> = { new (model: M): T };
interface GenericBuilder {
  <M = any, T = any>(View: V<M, T>, m: M): T;
  <M = any, T = any>(View: V<M, T>, m: M[]): Array<T>;
  <M = any, T = any>(View: V<M, T>, m: M | Array<M>): T | T[];
}

export const builder: GenericBuilder = <M = any, T = any>(
  View: ViewClass<M, T>,
  m: M | Array<M>
) => (Array.isArray(m) ? m.map((l) => new View(l)) : new View(m));


const model = { x: 2 };
class MyView {
   model: any;
   constructor(model) { this.model = model }
   get y() { 
     return this.model.x * 2;
   }
};
const result = builder(V, model);
assert(result.y == 2); // passes tsc
const list = builder(V, [model]);
assert(list.map(r => r.y) == [2]); // passes tsc

一旦我尝试使用构建器函数在类周围引入包装函数,类型就会退回到 T | 的实现。 T[] 而不是接口中提供的覆盖。

export function view<M = any, T = any>(View: V<M,T>, T>) {
  return {
    build: (m: M | M[]) => builder(View, m),
  };
}
const Wrapped = view(MyView)
Wrapped.build(model).y // fails tsc
Wrapped.build([model]).map(r => r.y) // fails tsc

【问题讨论】:

    标签: typescript typescript-typings typescript-generics


    【解决方案1】:
    export function view<M = any, T = any>(View: V<M,T>) {
      return {
        build: (m: M | M[]) => builder(View, m),
      };
    }
    

    您的view 包装器有一个属性build,它接受一个参数M | M[]。推断的返回类型为T | T[]。这里要注意的重要一点是 build 只有 一个 调用签名。你希望 Typescript 知道调用 build(M)build(M[]) 是不同的,但你还没有告诉它。

    可能有更简洁的方法可以做到这一点,但您绝对可以通过重载build 函数来实现您想要的。

    export function view<M = any, T = any>(View: V<M, T>) {
    
      function build(m: M): T;
      function build(m: M[]): T[];
      function build(m: M| M[]): T | T[];
      function build(m: M| M[]): T | T[] {
        return builder(View, m);
      }
      
      return {
        build
      };
    }
    

    Typescript Playground Link

    【讨论】:

      猜你喜欢
      • 2021-03-10
      • 2019-03-02
      • 1970-01-01
      • 2019-02-10
      • 2019-01-04
      • 2020-01-23
      • 2021-09-12
      • 1970-01-01
      相关资源
      最近更新 更多