Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript 泛型函数中的默认参数_Typescript - Fatal编程技术网

Typescript 泛型函数中的默认参数

Typescript 泛型函数中的默认参数,typescript,Typescript,我有一个带有签名的函数zip: function zip<T, U, V>(ts: T[], us: U[], zipper: (t: T, u: U) => V): V[] 这会产生(某种程度上预期的)编译错误,即(T,U)=>[T,U]不能分配给(T,U)=>V 最后,我用一组有点难看的重载解决了这个问题: export function zip<T, U>(ts: T[], us: U[]): [T, U][] export function zip<

我有一个带有签名的函数
zip

function zip<T, U, V>(ts: T[], us: U[], zipper: (t: T, u: U) => V): V[]
这会产生(某种程度上预期的)编译错误,即
(T,U)=>[T,U]
不能分配给
(T,U)=>V

最后,我用一组有点难看的重载解决了这个问题:

export function zip<T, U>(ts: T[], us: U[]): [T, U][]
export function zip<T, U, V>(
    ts: T[],
    us: U[],
    zipper: (t: T, u: U) => V
): V[]
export function zip<T, U>(
    ts: T[],
    us: U[],
    zipper: (t: T, u: U) => [T, U] = (t, u) => [t, u]
): [T, U][] {
    /* ... */
}
导出函数zip(ts:T[],us:U[]):[T,U][]
导出函数zip(
ts:T[],
美国:U[],
拉链:(t:t,u:u)=>V
):V[]
导出函数zip(
ts:T[],
美国:U[],
拉链:(t:t,u:u)=>[t,u]=(t,u)=>[t,u]
):[T,U][]{
/* ... */
}
这种方法有两个问题:

  • 基本上,签名
    zip(T[],U[]):[T,U][
    被呈现两次(第一次重载和实现本身)
  • 实现的签名不是最通用的,因为(特别是在更复杂的情况下)可能会导致错误

  • 有没有更好的方法来满足我的要求?第一次尝试时出现的错误是否是编译器错误(似乎不是,但如果是,肯定会使解决方案更简单)?

    您可以限制
    V

    function zip<T, U, V extends [T, U]>(
        ts: T[],
        us: U[],
        zipper: (t: T, u: U) => V = (t, u) => (<V>[t, u])
    )
    

    您可以限制您的
    V

    function zip<T, U, V extends [T, U]>(
        ts: T[],
        us: U[],
        zipper: (t: T, u: U) => V = (t, u) => (<V>[t, u])
    )
    

    这个错误是好的;泛型类型参数由函数的调用者指定,而不是由实现者指定。TypeScript很乐意推断参数,并使开发人员不用指定它们,但它们仍然是根据调用者的需要而不是实现者的需要推断出来的。这意味着无论谁调用
    zip()
    ,都可以选择他们想要的
    T
    U
    V
    。TypeScript正确地警告您,函数的实现不能假定
    V
    将与
    [T,U]
    兼容。使用原始签名和默认参数,调用者可以自由调用
    zip([“a”],[1])
    。是的,这太疯狂了,不,你不能实现它。因此,编译器正在帮助您解决警告问题


    重载是解决此问题的合理方法。你的签名很好。至于实现签名,是的,您应该使其更通用,记住
    zippers
    参数必须是可选的。但是,请注意,您必须声明默认的
    zipper
    返回一个
    V
    ,因为编译器仍然无法根据实现签名保证该值为真(即使您知道它是安全的,因为重载限制了可以进行的调用)。下面是一个例子:

    export function zip<T, U>(ts: T[], us: U[]): [T, U][]
    export function zip<T, U, V>(
        ts: T[],
        us: U[],
        zipper: (t: T, u: U) => V
    ): V[]
    export function zip<T, U, V>(
        ts: T[],
        us: U[],
        zipper?: (t: T, u: U) => V  // note the question mark
    ): V[] {
      if (!zipper) {
        zipper = (t, u) => ([t, u] as any as V); // note the assertion
      }
      const ret: V[] = []
      const len = Math.min(ts.length, us.length);
      for (let i = 0; i < len; i++) {
        ret.push(zipper(ts[i], us[i]));
      }
      return ret;
    }
    
    导出函数zip(ts:T[],us:U[]):[T,U][]
    导出函数zip(
    ts:T[],
    美国:U[],
    拉链:(t:t,u:u)=>V
    ):V[]
    导出函数zip(
    ts:T[],
    美国:U[],
    拉链?:(t:t,u:u)=>V//注意问号
    ):V[]{
    如果(!拉链){
    zippers=(t,u)=>([t,u]与V一样);//注意断言
    }
    常数ret:V[]=[]
    常数len=数学最小值(ts.length,us.length);
    for(设i=0;i
    这基本上就是TypeScript中重载的情况。编译器在检查实现时并不真正理解重载的签名。一旦使用重载,您就告诉编译器您将负责确保实现是安全的


    无论如何,希望这有帮助;祝你好运

    这是一个很好的错误;泛型类型参数由函数的调用者指定,而不是由实现者指定。TypeScript很乐意推断参数,并使开发人员不用指定它们,但它们仍然是根据调用者的需要而不是实现者的需要推断出来的。这意味着无论谁调用
    zip()
    ,都可以选择他们想要的
    T
    U
    V
    。TypeScript正确地警告您,函数的实现不能假定
    V
    将与
    [T,U]
    兼容。使用原始签名和默认参数,调用者可以自由调用
    zip([“a”],[1])
    。是的,这太疯狂了,不,你不能实现它。因此,编译器正在帮助您解决警告问题


    重载是解决此问题的合理方法。你的签名很好。至于实现签名,是的,您应该使其更通用,记住
    zippers
    参数必须是可选的。但是,请注意,您必须声明默认的
    zipper
    返回一个
    V
    ,因为编译器仍然无法根据实现签名保证该值为真(即使您知道它是安全的,因为重载限制了可以进行的调用)。下面是一个例子:

    export function zip<T, U>(ts: T[], us: U[]): [T, U][]
    export function zip<T, U, V>(
        ts: T[],
        us: U[],
        zipper: (t: T, u: U) => V
    ): V[]
    export function zip<T, U, V>(
        ts: T[],
        us: U[],
        zipper?: (t: T, u: U) => V  // note the question mark
    ): V[] {
      if (!zipper) {
        zipper = (t, u) => ([t, u] as any as V); // note the assertion
      }
      const ret: V[] = []
      const len = Math.min(ts.length, us.length);
      for (let i = 0; i < len; i++) {
        ret.push(zipper(ts[i], us[i]));
      }
      return ret;
    }
    
    导出函数zip(ts:T[],us:U[]):[T,U][]
    导出函数zip(
    ts:T[],
    美国:U[],
    拉链:(t:t,u:u)=>V
    ):V[]
    导出函数zip(
    ts:T[],
    美国:U[],
    拉链?:(t:t,u:u)=>V//注意问号
    ):V[]{
    如果(!拉链){
    zippers=(t,u)=>([t,u]与V一样);//注意断言
    }
    常数ret:V[]=[]
    常数len=数学最小值(ts.length,us.length);
    for(设i=0;i
    这基本上就是TypeScript中重载的情况。编译器在检查实现时并不真正理解重载的签名。一旦使用重载,您就告诉编译器您将负责确保实现是安全的


    无论如何,希望这有帮助;祝你好运

    V
    限制为
    [T,U]
    会对功能界面造成不必要的限制,但不会造成任何
    运行时危害。将
    V
    限制为
    [T,U]
    会对功能界面造成不必要的限制,而不会造成任何
    运行时危害。