Typescript 我如何才能摆脱部分<;T>;不在打字脚本中转换为T

Typescript 我如何才能摆脱部分<;T>;不在打字脚本中转换为T,typescript,Typescript,一般的类型脚本问题是,我迭代一个数组,我知道它的内容,然后应用reduce得到一个我确实知道类型的对象 例如: interface IMyInterface { a: number; b: number; c: number; } const result: IMyInterface = ['a','b','c'].reduce((acc: Partial<IMyInterface>,val)=>({...acc,[val]: 1}), {}); 接口IMyInt

一般的类型脚本问题是,我迭代一个数组,我知道它的内容,然后应用reduce得到一个我确实知道类型的对象 例如:

interface IMyInterface {
  a: number;
  b: number;
  c: number;
}
const result: IMyInterface = ['a','b','c'].reduce((acc: Partial<IMyInterface>,val)=>({...acc,[val]: 1}), {});
接口IMyInterface{
a:数字;
b:数字;
c:数字;
}
常量结果:IMyInterface=['a','b','c'].reduce((acc:Partial,val)=>({…acc,[val]:1}),{});
现在这不起作用了,因为预期结果是
部分的
,这是有意义的,考虑到TS不能告诉数组的内容将生成“完整”对象。 但是,我需要做什么才能使结果可以是IMyInterface类型,而不需要将
作为IMyInterface

这是回复


提前感谢

我遇到了同样的问题,通过将
acc
转换为所需的界面,并将初始值转换为
any
,我能够按需要运行:

const result= ['a','b','c'].reduce((acc: IMyInterface,val)=>({...acc,[val]: 1}), {} as any);

这应该将
result
设置为
IMyInterface
类型,而不会引起tslint错误。

这里的简短回答是:您非常需要使用,因为不可能让编译器知道您所做的是安全的


更长的答案是:为了让编译器知道发生了什么,您需要调用。这里有一种输入方法:

const cb = <K extends keyof IMyInterface, T extends Partial<IMyInterface>>(
    acc: T, val: K): T & Record<K, number> => ({ ...acc, [val]: 1 })
在这里,您可以看到编译器确实在为您着想,因为如果您以错误的方式调用
cb()
,您会收到一个错误提示

不幸的是

reduce(
callbackfn:(上一个值:U,当前值:T,当前索引:number,数组:readonly T[])=>U,
初始值:U
):U;
不足以表示每次对数组元素调用
callbackfn
时发生的连续类型收缩。据我所知,没有办法改变它来达到这个目的。你想说,
callbackfn
类型是一些类型的疯狂交集,对应于数组中每个连续成员的行为,比如
((p:A,c:this[0])=>B)和((p:B,c:this[1])=>c)和((p:c,c:this[2])=>D)和…
,对于泛型参数
A
B
c
D
,等等,然后希望编译器可以从您对
reduce()
的调用中推断出这些参数。不可能。这种语言不是语言的一部分(至少从TS3.7开始)

所以,这就是我们必须停止的地方。您可以展开循环并调用
cb(cb(…
),或者调用
reduce()
并使用类型断言。我认为类型断言真的没有那么糟糕;它专门用于您比编译器更聪明的情况……这似乎是其中之一

好吧,希望能有帮助,祝你好运


使用
reduce()
?可能没有什么比类型断言更好的了;为了让它工作,回调需要是泛型的
(acc:T,val:K):T&Record=>…
但是类型系统缺乏表达为元组类型的每个元素指定
T
K
的高阶操作的能力
[“a”、“b”、“c”]
。您可以这样做,但不能在循环或
reduce()中
@jcalz我不明白这是怎么回事。抱歉。在展开示例中,有一个对any的转换,然后从any到record的转换,这不是展开示例,很抱歉,这里有一个更多。这很有效,但只是因为编译器看到每个步骤分别发生。感谢您的响应。因此,我正在寻找一些不需要的东西uire casting。这包括对任何对象的casting。有趣的是,它实际上是错误的,因为在第一次迭代中acc是空的,我们说有IMyInterface类型,但实际上它不是一个PartialYes,从技术上讲它在减速器内部是错误的,但在这些特定情况下,这已经完成了工作,我正在转换一个known quantity使用一个非常简单、简洁的减缩器。由于函数很短,我放弃了寻找一个更“正确”的解决方案——我只关心最终结果是否正确键入。不过,在更复杂的情况下,我同意在函数中键入正确的内容会更好。
const result: IMyInterface = cb(cb(cb({}, "a"), "b"), "c"); // okay
const stillOkay: IMyInterface = cb(cb(cb({}, "a"), "c"), "b"); // okay
const mistake: IMyInterface = cb(cb(cb({}, "b"), "b"), "c"); // error! property "a" is missing
reduce<U>(
  callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: readonly T[]) => U, 
  initialValue: U
): U;