如何将函数参数定义为两种类型之一

时间:2021-03-07 04:31:45

标签: typescript

如何编译。

type Matchmaker = (data: MatcherData, name: string) => string
type MatcherData = RegExp | Array<string>

function makeDataUser(fU: (data: MatcherData) => string): Matchmaker {
    return function (data: MatcherData, name: string): string {
      return fU(data) + name;
    }
}


const user1 = makeDataUser((data: MatcherData): string => {
    if (typeof data === 'regexp') {
        if ("lkajdsf".match(data)) {
            return "yes";
        }
        return "no";
    } else {
        return data.join('');
    }
});

const user2 = makeDataUser((data: MatcherData): string => {
    if (typeof data !== 'regexp') {
        return "yes";
    } else {
        return "no";
    }
}


const mRegexUser = user1(/regex/, 'name');
const mArrayUser = user2(['lkajf'], 'name2');

我想要一个函数参数是两种类型中的任何一种,并且在任何一种情况下都使用它。

诀窍是我知道 user1 总是期望 RegExp,而 user2 总是期望 Array<string>。但我想为他们提供上面的通用功能。

1 个答案:

答案 0 :(得分:0)

如果在 data 函数中切换检查 Matchmaker 类型的顺序,编译器将能够缩小类型。您需要先将其缩小为是数组或不是数组,因为您发现没有 typeof <regexp type>

const user1 = makeDataUser((data: MatcherData): string => {
  if (Array.isArray(data)) {
    return data.join("");
  } else {
    if ("lkajdsf".match(data)) {
      return "yes";
    }
    return "no";
  }
});

const user2 = makeDataUser((data: MatcherData): string => {
  if (Array.isArray(data)) {
    return "no";
  } else {
    return "yes";
  }
});

如果你以后有更复杂的类型,你可以考虑使用一个discriminated union,在这里你选择一个关键属性(下面的type)来告诉编译器如何区分(区分)不同的分支工会的。

type Matchmaker = (data: MatcherData, name: string) => string;
type MatcherData =
  | {
      type: "RegExp";
      value: RegExp;
    }
  | {
      type: "Other";
      value: Array<string>;
    };

function makeDataUser(fU: (data: MatcherData) => string): Matchmaker {
  return function (data: MatcherData, name: string): string {
    return fU(data) + name;
  };
}

const user1 = makeDataUser((data: MatcherData): string => {
  if (data.type === "RegExp") {
    if ("lkajdsf".match(data.value)) {
      return "yes";
    }
    return "no";
  } else {
    return data.value.join("");
  }
});

const user2 = makeDataUser((data: MatcherData): string => {
  if (data.type === "RegExp") {
    return "yes";
  } else {
    return "no";
  }
});

const mRegexUser = user1({ type: "RegExp", value: /regex/ }, "name");
const mArrayUser = user2({ type: "Other", value: ["lkajf"] }, "name2");