簡體   English   中英

Typescript Array.isArray 保護語句和 function 上的返回類型

[英]Typescript Array.isArray guard statement and return types on function

我有以下 function 可以按預期工作,如果將數組傳遞給第二個參數,則返回類型被正確鍵入為泛型 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

一旦我嘗試使用構建器 function 在 class 周圍引入包裝器 function 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
export function view<M = any, T = any>(View: V<M,T>) {
  return {
    build: (m: M | M[]) => builder(View, m),
  };
}

您的view包裝器有一個屬性build ,它接受一個參數M | M[] M | M[] 推斷的返回類型是T | T[] T | T[] 這里要注意的重要一點是build只有一個調用簽名。 您期望 Typescript 知道調用build(M)build(M[])是不同的,但您沒有告訴它。

可能有一種更簡潔的方法可以做到這一點,但您絕對可以通過重載build function 來實現您想要的。

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 游樂場鏈接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM