typescript - 如何在 typescript 中检查函数中类型联合的类型

标签 typescript

假设我有这个代码:

interface A {
 type: 'a',
 value : number
}

interface B {
  type: 'b',
  value: string
}

type AB = A | B;

const db: Record<string, AB> = {
  param1: { type: 'a', value: 1234 }
};

我有这样的代码(过于简化),效果很好

function processParameter(parameter: string, expectedType: 'a' | 'b') {
  if (expectedType === 'a') {
    const result = db[parameter];
    if(!result) { throw new Error('Not found'); }
    if(result.type !== 'a') { throw new Error('Unexpected type'); }
    processA(result);
  }
  if (expectedType === 'b') {
    const result = db[parameter];
    if(!result) { throw new Error('Not found'); }
    if(result.type !== 'b') { throw new Error('Unexpected type'); }
    processB(result);
  }
}

function processA(value: A) {
  // ...
}

function processB(value: B) {
  // ...
}

我想像这样重构代码:

function processParameter(parameter: string, expectedType: 'a' | 'b') {
  if (expectedType === 'a') {
    const result = getAndCheck(parameter, expectedType);
    processA(result);
  }
  if (expectedType === 'b') {
    const result = getAndCheck(parameter, expectedType);
    processB(result);
  }
}

// I don't want to write all those lines here, is there a way ?
function getAndCheck(parameter: string, expectedType: 'a'): A;
function getAndCheck(parameter: string, expectedType: 'b'): B;
function getAndCheck(parameter: string, expectedType: 'a' | 'b'): AB {
  const result = db[parameter];
  if(!result) { throw new Error('Not found'); }
  if(result.type !== expectedType) { throw new Error('Unexpected type'); }
  return result;
}

有办法简化吗?使用通用?使用推理 ?我是不是走错路了?

最佳答案

您可以使用泛型函数在 expectedType 参数和返回类型之间建立关系:

function getAndCheck<K extends AB['type']>(parameter: string, expectedType: K): Extract<AB, { type: K }> {
    const result = db[parameter] as AB;
    if (!result) { throw new Error('Not found'); }
    if (result.type !== expectedType) { throw new Error('Unexpected type'); }
    return result as Extract<AB, { type: K }>;
}

Playground Link

这里我们使用类型参数K来捕获传入的实际类型,并确保只能传入联合体AB中的类型(我们使用 index access type 来获取所有可能类型的并集)。然后,我们使用 Extract 从联合中获取适当的元素。 (您可以阅读更多关于过滤联合的信息 here )

关于typescript - 如何在 typescript 中检查函数中类型联合的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71600840/

相关文章:

typescript - 有没有办法在初始化时在nextjs中同时配置tailwind和typescript?

angular - 让 Amazon Cognito 使用 angular2 和 typescript

javascript - 返回值的 bool 函数

在断言另一个属性后对一个属性进行 typescript 推断

javascript - 如何重定向到另一个组件页面 Angular 5

javascript - Webpack 错误 TS2339 : Property 'dialog' does not exist on type 'JQuery'

javascript - Angular从html中的控件获取值

javascript - 移动焦点() - Angular 5

reactjs - 带有两个窗口的 electron-forge : how to render the second window? electron-react app

typescript - 在 'export declare function' 文件中使用 'export function' 和 '.d.ts' 有什么区别