打字稿泛型 >联合约束 [英] Typescript > Generics > Union Constraint

查看:26
本文介绍了打字稿泛型 >联合约束的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么打字稿编译器会抛出以下错误:

Why does the typescript compiler throw the following error:

运算符+"不能应用于类型T"和T".,

编译时:

export const addNumbersOrCombineStrings = <T extends string | number>(
  param1: T,
  param2: T
): T => param1 + param2

?

推荐答案

GitHub 中的相关问题是 微软/TypeScript#12410.您的特定问题在 评论 中由 Ryan Cavanaugh:

The relevant issue in GitHub is Microsoft/TypeScript#12410. Your particular question is addressed in a comment by Ryan Cavanaugh:

T + T 其中 T 扩展 string |number 仍然是不允许的——我们认为这不是一个好的用例,因为你是否得到连接或加法是不可预测的,因此人们不应该这样做.

T + T where T extends string | number is still disallowed -- we don't feel this is a good use case because whether you get concatenation or addition is not predictable, thus something that people shouldn't be doing.

如果你只是尝试添加两个 string | 也会发生同样的事情.number 一起输入:

The same thing happens to you if you just try to add two string | number types together:

declare const x: string | number;
x + x; // error!
// Operator '+' cannot be applied to types 'string | number' and 'string | number'.

所以我猜他们是认真的,他们不想让你这样做.您可以随时根据自己的意愿弯曲编译器并使用 类型断言;

So I guess they are serious that they don't want you doing that. You can always bend the compiler to your will and disable the type check with a type assertion;

export const addNumbersOrCombineStrings = <T extends string | number>(
  param1: T,
  param2: T
): T => (param1 as any) + param2;

但是您不想这样做,尤其是因为 T extends string |number推断一个stringnumber 字面量,它不会为您提供预期的行为:

But you don't want to do this, especially since T extends string | number will infer a string or number literal, which does not give you the behavior you expect:

const notThree = addNumbersOrCombineStrings(1, 2);
// const notThree: 1 | 2

const notHi = addNumbersOrCombineStrings("h", "i");
// const notHi: "h" | "i"

糟糕,这些结果是文字的联合.为了用泛型解决这个问题,你可能想开始使用花哨的 条件类型 来加宽文字:

Oops, those results are unions of literals. And to fix that with generics you'd probably want to start using fancy conditional types to widen the literals:

type SN<T extends string | number> = (T extends string ? string : never) | 
  (T extends number ? number : never);

export const addNumbersOrCombineStrings = <T extends string | number>(
  param1: T,
  param2: SN<T>
): SN<T> =>
  (param1 as any) + param2;

const n = addNumbersOrCombineStrings(1, 2); // const n : number;
const s = addNumbersOrCombineStrings("h","i"); // const s: string;

// and do you even want to support this:
const sn = addNumbersOrCombineStrings(
  Math.random() < 0.5 ? "a" : 1,
  Math.random() < 0.5 ? "b" : 2
); // const sn: string | number;

但也可能存在边缘情况(例如,当传入的值实际上是 string | number 时,就像上面的 sn 情况一样).我开始明白为什么他们不喜欢支持添加 string | 类型的值.号 在一起.无论如何,希望有帮助.祝你好运!

But there are edge cases there too, probably (like when the value passed in is actually string | number like the sn case above). I'm starting to see why they don't feel like supporting adding values of type string | number together. Anyway, hope that helps. Good luck!

这篇关于打字稿泛型 >联合约束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆