【问题标题】:How do I typecast in an overloaded function with generics in TypeScript如何在 TypeScript 中使用泛型在重载函数中进行类型转换
【发布时间】:2015-05-04 21:56:53
【问题描述】:

在我正在开发的一个库中,我有一个方法可以确保某些东西属于IList 类型,如果不是,它应该将其转换为IList 类型的实例。请看下面的代码:

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,但这是不可接受的,因为它会导致其他地方出现打字问题。

有人知道我应该如何继续吗?

【问题讨论】:

    标签: generics casting typescript overloading


    【解决方案1】:

    请记住,实现签名是不可见的。当您在方法上有一组重载时,只有 不是 实现的签名在外部可见:

    // 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 的好时机,因为类型检查会带来麻烦而不是帮助。

    【讨论】:

      猜你喜欢
      • 2021-04-23
      • 1970-01-01
      • 2021-05-13
      • 2020-04-21
      • 1970-01-01
      • 2018-09-21
      • 1970-01-01
      • 2022-01-26
      • 2020-09-09
      相关资源
      最近更新 更多