Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

182
Visualizações
unionType cannot be generics Function Parameter in Typescript

I've defined a generics Function, and I'm trying to pass the union of two specific sample of the generics to the function, like

function myCommonFunc<T>({
  data,
  render,
}: {
  data: T;
  render: (data: T) => number;
}) {
  return render(data);
}

interface TestX<T> {
  data: T;
  render: (data: T) => number;
}

let z: TestX<number> | TestX<string>;
// let z: TestX<number | string>  is wrong, because T will be number | string


if ((window as any).someUserInput === 1) {
  z = { data: 1, render: (a: number) => 1 };
} else {
  z = { data: '1', render: (a: string) => 1 };
}

// someother function

myCommonFunc(z);

and it throw errs.

I guess the reason is the function cannot infer type from the unionType, and If so, what should I do?

I know one solution is to use typeguard of z, like

function isTypeA(z: TestX<number> | TestX<string>): z is TestX<number> {
  return typeof z.data === 'number';
}
if (isTypeA(z)) {
  myCommonFunc(z);
}

but I think it actually change the structure of the program, and it need lots if-else to just for typescript, which is annoying. Can someone give me some other way to solve it?

==========

update:

François's solution is helpful, but somehow it cannot solve the real situation, actually z is a state in React Function Component, and myCommonFunc is a Component, and I'll update the real code:

interface TestX<T> {
  data: T;
  render: (data: T) => number;
}

function MyCommonFunc<T>({ data, render }: TestX<T>) {
  return <>{render(data)}</>;
}

type myType = TestX<number> | TestX<string>;

const F = () => {
  const [z, setZ] = useState<myType>({ data: 1, render: (a: number) => 1 });
  const [userInput, setUserInput] = useState<number>(1);
  useEffect(() => {
    if (userInput === 1) {
      setZ({ data: 1, render: (a: number) => 1 });
    } else {
      setZ({ data: '1', render: (a: string) => 1 });
    }
  }, [userInput]);
  // someOther Code
  return <MyCommonFunc {...z} />;
};

So I cannot just move the function call to the if-else block. and I'm so sorry that not put the real code at the first time.

about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

This is a hard one. I see 3 solutions:

Solution 1

Solution 1 is the one you've mentioned above of using type guards:

const isTestNumber = (z: TestX<number> | TestX<string>): z is TestX<number> => {
  return typeof z.data === "number"
}

if (isTestNumber(z)) {
  myCommonFunc(z);
} else {
  myCommonFunc(z);
}

It is by far my least favorite solution.

Solution 2

Solution 2 is to cast z before passing it as a parameter. It looks like this:

myCommonFunc(z as TestX<any>); // ugly casting

I know it's ugly, but it's not particularly dangerous since the z variable is fully typed above. At least it does not alter the execution of the program.

Solution 3

Solution 3 requires some structural change to your program.

What you currently do is you declare the z variable, you assign it in an if-else statement and then you perform operations on it afterward.

What you could do is wrap all subsequent operations in another generic function.

It looks like this:

interface TestX<T> {
  data: T;
  render: (data: T) => number;
}

function myCommonFunc<T>(z: TestX<T>) {
  const { data, render } = z
  return render(data);
}

function allSubsequentOperations<T>(z: TestX<T>) {
  // someother function
  
  myCommonFunc(z);
}

if ((window as any).someUserInput === 1) {
  const z: TestX<number> = { data: 1, render: (a: number) => 1 };
  allSubsequentOperations(z)
} else {
  const z: TestX<string> = { data: "1", render: (a: string) => 1 };
  allSubsequentOperations(z)
}

This is what I usually do when dealing with this kind of problem. From the moment z is assigned, your whole program becomes generic.

I hope you find these answers helpful,

François

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda