2015-05-04 57 views
0

在我正在處理的庫中,我有一種方法可以確保IList類型的東西,如果不是,它會將其變爲IList類型的實例。請參見下面的代碼:如何在TypeScript中使用泛型重載函數進行類型轉換

1 import { IList, isList } from './list'; 
2 
3 import Unit  from './unit'; 
4 import ArrayList from './array_list'; 
5 
6 export default function factory<V,I>(obj: IList<V,I>): IList<V,I>; 
7 export default function factory<V>(obj: V[]): IList<V,number>; 
8 export default function factory<V>(obj: V): IList<V,number> { 
9  if(isList(obj)) return obj; 
10  if(Array.isArray(obj)) return new ArrayList(obj); 
11  return new Unit(obj); 
12 } 

這種方法編譯失敗,請參閱下面的錯誤:

src/factory.ts(9,30): 2322 Type 'V' is not assignable to type 'IList<V, number>'. 
    Property 'has' is missing in type '{}'. 
src/factory.ts(10,51): 2345 Argument of type 'V' is not assignable to parameter of type '{}[]'. 
    Property 'length' is missing in type '{}'. 
src/factory.ts(11,14): 2322 Type 'Unit<{}>' is not assignable to type 'IList<V, number>'. 
    Types of property 'get' are incompatible. 
    Type '(id: number) => {}' is not assignable to type '(id: number) => V'. 
     Type '{}' is not assignable to type 'V'. 

我不能確定如何解決此問題:當然,我可以簡單地聲明的返回類型該方法爲any,但這是不可接受的,因爲這會導致在別處輸入問題。

有誰知道我應該如何繼續?

回答

2

請記住,執行簽名不可見。當你有一組重載的方法,只有實施簽名外部看出:

// Visible to callers 
export default function factory<V,I>(obj: IList<V,I>): IList<V,I>; 
// Visible to callers 
export default function factory<V>(obj: V[]): IList<V,number>; 
// *Not* visible to callers 
export default function factory<V>(obj: V): IList<V,number> { 
    if(isList(obj)) return obj; 
    if(Array.isArray(obj)) return new ArrayList(obj); 
    return new Unit(obj); 
} 

這最後的簽名必須是自己的過載,像這樣。

// Visible to callers 
export default function factory<V,I>(obj: IList<V,I>): IList<V,I>; 
// Visible to callers 
export default function factory<V>(obj: V[]): IList<V,number>; 
// Visible to callers 
export default function factory<V>(obj: V): IList<V,number>; 
// Not seen by callers, so 'any' does not leak out 
export default function factory(obj: any): any { 
    if(isList(obj)) return obj; 
    if(Array.isArray(obj)) return new ArrayList(obj); 
    return new Unit(obj); 
} 

由於呼叫者可以看不到實現的簽名,無論如何,這是使用any因爲類型檢查將是更討厭而不是幫助的好時機。