如何在 TypeScript 中使用泛型在重载函数中进行类型转换
How do I typecast in an overloaded function with generics in TypeScript
在我正在处理的库中,我有一个方法可以确保某些东西属于 IList
类型,如果不是,它应该将它变成 [=12] 类型的实例=].请看下面的代码:
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'.
我不确定如何解决这个问题:当然,我可以简单地将方法的 return 类型声明为 any
,但这是不可接受的,因为它会导致输入问题别处。
有人知道我应该如何继续吗?
请记住,实现签名不可见。当你在一个方法上有一组重载时,只有不是实现的签名在外部可见:
// 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
的好时机,因为类型检查会带来麻烦而不是帮助。
在我正在处理的库中,我有一个方法可以确保某些东西属于 IList
类型,如果不是,它应该将它变成 [=12] 类型的实例=].请看下面的代码:
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'.
我不确定如何解决这个问题:当然,我可以简单地将方法的 return 类型声明为 any
,但这是不可接受的,因为它会导致输入问题别处。
有人知道我应该如何继续吗?
请记住,实现签名不可见。当你在一个方法上有一组重载时,只有不是实现的签名在外部可见:
// 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
的好时机,因为类型检查会带来麻烦而不是帮助。