简体   繁体   English

TypeScript 通用 function 的条件返回类型

[英]TypeScript conditional return type for generic function

I want to create a function which makes it easy to infer the structure of the run method inside the task definition below.我想创建一个 function ,它可以很容易地在下面的任务定义中推断run方法的结构。 Is it possible to create a conditional return value so that inferTest1 has the type { skipped: boolean; result: number }是否可以创建一个条件返回值,以便inferTest1具有类型{ skipped: boolean; result: number } { skipped: boolean; result: number } and inferTest2 receives the type { skipped: boolean } without a result property? { skipped: boolean; result: number }inferTest2接收类型{ skipped: boolean }没有结果属性?

interface TaskDefinition<T> {
  run: () => { skipped: boolean } | { skipped: boolean; result: T };
}

function createTask<T>(
  task: TaskDefinition<T>
): { skipped: boolean; result: T } | { skipped: boolean } {
  const taskResult = task.run();
  if ("result" in taskResult) {
    return {
      skipped: taskResult.skipped,
      result: taskResult.result,
    };
  }
  return {
    skipped: taskResult.skipped,
  };
}

const inferTest1 = createTask({
  run: () => ({
    skipped: false,
    result: 251,
  }),
});

const inferTest2 = createTask({
  run: () => ({
    skipped: false,
  }),
});

I think the simplest solution here would be to use overloads:我认为这里最简单的解决方案是使用重载:

interface TaskDefinition<T> {
  run: () => { skipped: boolean } | { skipped: boolean; result: T };
}

function createTask<T>(task: { run: () => { skipped: boolean; result: T } }): { skipped: boolean; result: T }
function createTask(task: { run: () => { skipped: boolean } }): { skipped: boolean }
function createTask<T>(task: TaskDefinition<T>): { skipped: boolean; result: T } | { skipped: boolean } {
  const taskResult = task.run();
  if ("result" in taskResult) {
    return {
      skipped: taskResult.skipped,
      result: taskResult.result,
    };
  }
  return {
    skipped: taskResult.skipped,
  };
}

const inferTest1 = createTask({
  run: () => ({
    skipped: false,
    result: 251,
  }),
});
inferTest1.result

const inferTest2 = createTask({
  run: () => ({
    skipped: false,
  }),
});
inferTest2.result // err

Playground Link 游乐场链接

You could also use conditional types, but I think that is overkill here.你也可以使用条件类型,但我认为这有点过分了。

Another solution would be to infer the result of run itself, although that might interfere with other things you are doing in the function:另一种解决方案是推断运行本身的结果,尽管这可能会干扰您在 function 中执行的其他操作:


function createTask<T extends { skipped: boolean } | { skipped: boolean; result: T }>(task: { run: () => T }): T {
    const taskResult = task.run();
    // Only spreading or type assertions will work to satisfy T, also narrowing is now borken
    return {
        ...taskResult
    };
}

Playground Link 游乐场链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM