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
returnnever
——因为我们的项目没有要求它。所以次(三米,四牛顿)
只返回从不
。然而,我们也有一个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">