打字稿:类型“ T”不可分配给类型“ IArgs”-如何编写两种类型

时间:2020-11-11 21:03:22

标签: typescript generics types

我刚接触Typescript。

我正在尝试执行以下操作:定义一个函数对象,其中所有对象函数都带有某些自变量,并可选地具有其他类型的自变量。

我走错了兔子洞吗?任何帮助都非常感谢!

interface ITaskArgs<T> {
  deal: { id: string }
  genericArgs?: T
}

type Tasks = {
    DEPOSIT: {
      create: <T>(args: ITaskArgs<T>) => Promise<any>
      update: <T>(args: ITaskArgs<T>) => Promise<any>
      complete: <T>(args: ITaskArgs<T>) => Promise<any>
    }
}
  

type CompleteArgs = {
    completeArg: string
}

type UpdateArgs = {
    updateArg: string
}


const tasks: Tasks = {
    // other tasks with other functions
      DEPOSIT: {
        create: (args: ITaskArgs<null>) => {
            // only args.deal available here
            return Promise.resolve()
        },
        update: (args: ITaskArgs<UpdateArgs>) => {
            // needs args.genericArgs.updateArg here 
            return Promise.resolve()
        },
        // other functions
        complete: (args: ITaskArgs<CompleteArgs>) => {

          const { genericArgs, deal } = args
          // how do I get genericArgs.completeArg here?

          return Promise.resolve()
        }
    }
}

const testTasks = tasks

// should pass
testTasks.DEPOSIT.create({ deal: { id: "1" }})
testTasks.DEPOSIT.update({ deal: { id: "1" }, genericArgs: { updateArg: "4" }})
testTasks.DEPOSIT.update({ deal: { id: "1" }, genericArgs: { completeArg: "4" }})

// should error because genericArgs is typed as null but passed here
testTasks.DEPOSIT.create({ deal: { id: "1" }, genericArgs: { failForPassing: "4" }})
// should error because `randomArg` isn't an `UpdateArgs` and `updateArg` not passed
testTasks.DEPOSIT.update({ deal: { id: "1" }, genericArgs: { randomArg: "4" }})
// should error because `randomArg` isn't an `UpdateArgs`
testTasks.DEPOSIT.update({ deal: { id: "1" }, genericArgs: { randomArg: "4", updateArg: "5" }})
// should error because `completeArg` isn't an `UpdateArgs` and `updateArg` not passed
testTasks.DEPOSIT.update({ deal: { id: "1" }, genericArgs: { completeArg: "4" }})
// should error because `updateArg` not passed
testTasks.DEPOSIT.update({ deal: { id: "1" }, genericArgs: {}})
// should error because `completeArg` not passed
testTasks.DEPOSIT.complete({ deal: { id: "1" }})

错误是:

Type '(args: ITaskArgs<IArgs>) => Promise<void>' is not assignable to type '<T>(args: ITaskArgs<T>) => Promise<any>'.
  Types of parameters 'args' and 'args' are incompatible.
    Type 'ITaskArgs<T>' is not assignable to type 'ITaskArgs<IArgs>'.
      Type 'T' is not assignable to type 'IArgs'.(2322)
input.tsx(8, 7): The expected type comes from property 'complete' which is declared here on type '{ complete: <T>(args: ITaskArgs<T>) => Promise<any>; }'

Typescript Playground

1 个答案:

答案 0 :(得分:0)

更新 第二种方法: 只是让TypeScript为您推断类型,不要为参数提供类型:

interface ITaskArgs<T> {
  deal: { id: string }
  genericArgs?: T
}

// **UPDATED**
type Tasks = {
    DEPOSIT: {
       create: <T>(args: ITaskArgs<T>) => Promise<any>
       update: <T extends { updateArg: string }>(args: ITaskArgs<T>) => Promise<any>
       complete: <T extends { completeArg: string }>(args: ITaskArgs<T>) => Promise<any>
    }
}
  

type IArgs = {
    arg: string
}


type IArgs2 = {
    arg2: string
}

const tasks: Tasks = {
    // other tasks with other functions
    DEPOSIT: {
        create: (args) => {
            // only args.deal available here
            return Promise.resolve()
        },
        update: (args) => {
            // needs args.genericArgs.arg2 here 
            return Promise.resolve()
        },
        // other functions
        complete: (args) => {

          const { genericArgs, deal } = args
          // how do I get genericArgs.arg here?

          return Promise.resolve()
        }
    }
}