TypeScript函数,其参数应接受两种类型之一

时间:2019-10-03 20:47:53

标签: typescript

我正在尝试创建一个函数,其参数可以是两种类型之一。然后,该函数可以调用另一个函数。但是,我收到一条错误消息。您可以在下面看到脚本和屏幕截图。如何编写此函数,使其可以接受两种类型之一的参数?谢谢!

interface A {
  a: string;
  title: string,
}

interface B {
  b: number;
  title: string;
}

const alpha = (data: A) => data.a;

const beta = (data: B) => data.b;

const foo = (data: A | B) => {
  if (data.title === 'a') {
    return alpha(data);  // Message: "Argument type A | B is not assignable to type A"
  }
  if (data.title === 'b') {
    return beta(data);  // Message: "Argument type A | B is not assignable to type B"
  }
};

enter image description here

4 个答案:

答案 0 :(得分:2)

请尝试在参数上使用type assertions(如强制转换),以便在确定类型后,编译器(和IDE)会将其视为适当的类型。

interface A {
  a: string;
  title: string,
}

interface B {
  b: number;
  title: string;
}

const alpha = (data: A) => data.a;

const beta = (data: B) => data.b;

const foo = (data: A | B) => {
  if (data.title === 'a') {
    return alpha(<A>data);
  }
  if (data.title === 'b') {
    return beta(<B>data);
  }
};
  

类型断言是一种告诉编译器“相信我,我知道我在做什么”的方法。类型断言就像其他语言中的类型转换一样,但是不执行任何特殊的数据检查或重组。它对运行时间没有影响,仅由编译器使用。 TypeScript假定您(程序员)已经执行了所需的任何特殊检查。

答案 1 :(得分:1)

您需要一个类型保护,它会告诉TS A对象的标题等于a,而B对象的标题则等于b

const isA = (x: A | B): x is A => x.title === 'a';
const isB = (x: A | B): x is B => x.title === 'b';

然后:

const foo = (data: A | B): any => {
  if (isA(data)) {
    return alpha(data);
  }
  if (isB(data)) {
    return beta(data);
  }
};

一个更好的选择是使区分值(ab)成为类型而不是字符串:

interface A1 {
  a: string;
  title: 'a',
}

interface B1 {
  b: number;
  title: 'b';
}

然后,您可以简单地使用switch作为类型防护:

const foo1 = (data: A1 | B1): any => {
  switch (data.title) {
    case 'a': return alpha(data);
    case 'b': return beta(data);
  }
};

Docs

PG

答案 2 :(得分:1)

问题在于打字稿不知道title === 'a'表示数据类型为a。幸运的是,您可以提供一个更窄的类型而不是string来帮助打字稿。

interface A {
  a: string;
  title: 'a' ; // title can now be 'a'  only, not any other string. 
}

interface B {
  b: number;
  title: 'b' ; // title can now be 'b'  only, not any other string. 
}

答案 3 :(得分:-7)

请使用any

const foo = (data: any) => {
  if (data.title === 'a' && checkA(data)) {
    return alpha(data);
  }
  if (data.title === 'b' && checkB(data)) {
    return beta(data);
  }
};

然后通过创建自己的函数来检查接口类型。

function checkA(obj: any) {
    return 'a' in obj;
}
function checkB(obj: any) {
    return 'b' in obj;
}