Typescript 手动加宽类型

Typescript 手动加宽类型,typescript,type-conversion,Typescript,Type Conversion,有没有办法指定我想要的类型是另一个类型的扩展版本 我的用例是这样的: function times<A extends number, B extends number>(a: A, b: B): A & B; 测量单位的功能时间(例如秒、英尺)。这意味着这些扩展实际上只存在于类型域中,而不存在于运行时中。这对我们有很多好处 我们的品牌数量是有限的(主要是In、Per和Delta,因此我们可以将常数v=20作为数字和In&Per或常数d=100作为数字和In&Delta)。

有没有办法指定我想要的类型是另一个类型的扩展版本

我的用例是这样的:

function times<A extends number, B extends number>(a: A, b: B): A & B;
测量单位的功能时间(例如秒、英尺)。这意味着这些扩展实际上只存在于类型域中,而不存在于运行时中。这对我们有很多好处


我们的品牌数量是有限的(主要是
In
Per
Delta
,因此我们可以将
常数v=20作为数字和In&Per
常数d=100作为数字和In&Delta
)。
times
函数有大量重载来覆盖所有这些情况。但是,我们也有很多通用容器,它们使用
N extends number
存储任何类型的品牌编号。正是这种情况导致了上述
次数过载的问题。让这些通用容器中的每一个单独处理所有可能出现的
In
Per
、和/或
Delta
的各种情况是不可能的(我认为也不可能),忘记了在

中的交叉点
,哦,你正在使用。因此,您希望将
6&In
扩展到
number&In
,而不仅仅是
number
。嗯…你能把这个编辑成一个吗?我认为这是一个有趣的问题,但我不想花时间给你一个不符合你的用例的解决方案。比如,我真诚地怀疑您是否真的想要
number&In&In
,因为这将等同于
number&In
您在
中定义的方式。我希望看到一些代码在类型级别上完全按照您所希望的方式工作,除了
times()
由于文本而无法工作之外。现在还不太清楚。@jcalz谢谢你的术语,我不知道有他们的名字。我们实际上并没有在分子或分母中处理多个单位,即
times
return
never
——因为我们的项目没有要求它。所以
次(三米,四牛顿)
只返回
从不
。然而,我们也有一个
Per
定义,类似于我们用作分母的
中的
。我们还使用了其他的“品牌”,比如
Delta
(虽然
的结果不多,但
返回它),还有一些需要支持的泛型;我对基本原理的描述过于简短,让你有点误入歧途:
number&in
并不是我们仅有的案例。特别是,
N扩展数字
出现了,我们对它一无所知,但我们希望保持
N
,只要它不是数字文字。问题更新,我道歉。是的,在许多情况下,
看起来有点像这样,但是对于我们不知道
中的
和/或
并且只有
N
的情况,我们有一个问题。听起来像是一个无法解决的问题。因此要求一个解决方案。正如我上面所说的,你必须知道一些关于它的事情,因为你不能像联合那样迭代或分布在交叉点上。您可能有一些有限的案例列表,因此您可以手动提取这些案例,如
编号&(N个扩展项In?In:未知)和(N个扩展项Per?Per:未知)&….
。您不控制原语的品牌化方式吗?真的是这样吗?你得到了一些
N扩展数
,却完全不知道与之相交的可能类型是什么?如果是这样,是的,你被卡住了。不过,我怀疑不是这样。所以,或多或少,是的,
要处理的情况是有限的,它确实如此,就像你在这里所做的那样,但是有每个通用的数字容器,比如
接口点{x:N,y:N}
接口框{x:N;y:N;w:N&Delta;h:N&Delta;}
Delta
As
其中
As
的定义与
中的
非常相似)也被迫处理所有这些迭代是有问题的。我们可以有一个通用的方法来处理以像素、英尺或赫兹为单位的数字(
Per
),或无量纲数。至于一个最小的可复制示例,虽然在问题中的一个之前,
有许多重载,但问题中的一个重载,特别是导致问题的重载,特别是在我们将一个
N扩展数
与一个文本相乘的情况下。Luckily、 我们目前只有少数此类案例,因此,如果没有更好的答案,将
转换为number
是可行的。
class In<T> { private __v!: T };

function withUnit<N extends number, T extends string>(n: N, t: T): N & In<T> {
  return n as any;
}
const oneNewton = withUnit(1, "Newtons"); // 1 & In<"Newtons">
const oneMeter = withUnit(1, "meter"); // 1 & In<meter>
type Widen<N extends number> = N extends In<infer T> ? number & In<T> : number;
declare function times<A extends number, B extends number>(a: A, b: B): Widen<A> & Widen<B>;
const six = times(2, 3); // number
const twoMeters = times(2, oneMeter); // number & In<"meter">
const alsoTwoMeters = times(oneMeter, 2); // number & In<"meter">;
const oneSquareMeterUhWait = times(oneMeter, oneMeter); // number & In<"meter">;    
const twoNewtonMetersUhWait = times(2, times(oneNewton, oneMeter)); 
// number & In<"Newtons" & "meter">