[英]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 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 cannnot infer type from the unionType, and If so, what should I do?我猜原因是 function 无法从 unionType 推断类型,如果是这样,我该怎么办?
I know one solution is to use typeguard of z, like我知道一种解决方案是使用 z 的 typeguard,例如
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.但我认为它实际上改变了程序的结构,并且它需要很多 if-else 才能仅用于 typescript,这很烦人。 Can someone give me some other way to solve it?
有人可以给我一些其他方法来解决它吗?
This is a hard one.这是一个很难的。 I see 3 solutions:
我看到了 3 个解决方案:
Solution 1 is the one you've mentioned above of using type guards:解决方案 1 是您上面提到的使用类型保护的解决方案:
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 is to cast z
before passing it as a parameter.解决方案 2 是在将
z
作为参数传递之前对其进行强制转换。 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.我知道这很丑陋,但它并不是特别危险,因为
z
变量在上面是完全输入的。 At least it does not alter the execution of the program.至少它不会改变程序的执行。
Solution 3 requires some structural change to your program.解决方案 3 需要对您的程序进行一些结构更改。
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.您当前所做的是声明
z
变量,在if-else
语句中分配它,然后对它执行操作。
What you could do is wrap all subsequent operations in another generic function.您可以做的是将所有后续操作包装在另一个通用 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.从分配
z
的那一刻起,您的整个程序就变得通用了。
I hope you find these answers helpful,我希望这些答案对您有所帮助,
François弗朗索瓦
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.