Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

183
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda