如何在typescript中有选择地从一个分部分配到另一个分部
在下面的TypeScript代码片段中,我需要从一个对象分配到另一个对象,其中两个对象都是如何在typescript中有选择地从一个分部分配到另一个分部,typescript,Typescript,在下面的TypeScript代码片段中,我需要从一个对象分配到另一个对象,其中两个对象都是Partial。这里,我的直觉告诉我typescript应该能够理解发生了什么,因为在第(B)行,key的类型是typeof InjectMap。因此,它应该能够将输入中的值正确分配给输出 export interface InjectMap { "A": "B", // line (A) "
Partial
。这里,我的直觉告诉我typescript应该能够理解发生了什么,因为在第(B)行,key
的类型是typeof InjectMap
。因此,它应该能够将输入
中的值正确分配给输出
export interface InjectMap {
"A": "B", // line (A)
"C": "D"
}
type InjectKey = keyof InjectMap;
const input: Partial<InjectMap> = {};
const output: Partial<InjectMap> = {};
const keys: InjectKey[] = []
for (let i = 0; i < keys.length; i++) {
const key = keys[i] // line (B)
output[key] = input[key] // line (C) - Gives Error
}
奇怪的是,如果我注释第(A)行,错误就会消失。这是TypeScript中的一个缺点还是我遗漏了什么?我不认为这是一个bug,变异值几乎总是不安全的,TS只是试图使其安全 让我们从
InjectMap
接口开始
很明显,您不能有以下非法状态:
const非法:InjectMap={
“A”:“D”,//应为B
“C”:“B”//D
}
这很重要
让我们继续循环:
接口映射{
“A”:“B”,
“C”:“D”
}
类型InjectKey=InjectMap的keyof;
常量输入:部分={};
常量输出:部分={};
常量键:InjectKey[]=[]
for(设i=0;i
由于键
是动态的,TS不确定它是B
、D
还是未定义
。我希望您同意我的观点,在这里,inp
的正确类型是“B”|“D”|未定义的
,这是预期的行为,因为类型系统是静态的
由于,输入
和输出
未被键
绑定,TS希望避免非法状态。为了说明清楚,请考虑下一个例子,它等于我们的
type KeyType=“B”|“D”|未定义
设keyB:KeyType_u2;='B';
让keyD:KeyType_uz='D'
输出[keyB]=输入[keyD]//爆炸,非法状态!运行时错误!
您可能已经注意到,keyB
和keyD
的类型相同,但值不同
与示例中的情况相同,TS无法计算出它只能计算出的值类型
如果要使TS满意,应添加条件语句或typeguard:
for(设i=0;i
请记住,当你改变你的值时,你会失去类型保证
请参阅并询问有关突变的信息
另外,提香·德拉戈米尔·塞尔尼科娃的这首歌也不错
这里有一个不安全突变的例子,摘自@Titian的演讲:
类型={
名称:string
}
类型a=类型&{
薪水:string
}
类型B=类型和{
汽车:布尔型
}
类型扩展=
你呢?对:错
让员工:子类型a={
姓名:“约翰·多伊”,
工资:1000美元
}
让人类:类型={
姓名:“摩根·弗里曼”
}
let director:b={
姓名:'威尔',
汽车:是的
}
//同方向
类型协方差={
方框:T
}
让员工收件箱:协方差={
方框:雇员
}
让humanInBox:协方差={
盒子:人
}
//对象属性的变异
let test:协方差=员工收件箱
test.box=主管//员工收件箱的变异
const result_uu=employeeInBox.box.salary//result_u未定义时,推断为字符串
//阵列突变
让数组:数组=[]
让雇员=[雇员]
数组=员工
array.push(控制器)
const result=employees.map(elem=>elem.salary)//当salary为[string,undefined]时,被推断为字符串[]
log({result,result})
如何修复它?
请让我知道它是否适合您:
导出接口映射{
“A”:“B”,
“C”:“D”
}
常量赋值=(
输入:部分,
产出:部分,
关键字:数组
)=>按键减少((acc,elem)=>({
…acc,
[elem]:输入[elem]
}),输出)
更新
为什么此分析适用于[elem]:输入[elem]?输入[elem]也可以是“B”|“D”|未定义的,因此编译器应该再次给出错误。但是,在这里,编译器很聪明,知道输入[elem]的类型适用于[elem]。有什么区别
这是一个很好的问题
当您使用计算键创建新对象时,TS使该对象按字符串索引,我的意思是,您可以使用任何字符串prop
const computedProperty=(prop:keyof InjectMap)=>{
常数结果={
[prop]:'someprop'/{[x:string]:string;}
}
返回结果
}
它给你更多的自由,但也提供了一点不安全
权力大,责任大
因为现在,不幸的是,你可以这样做:
const assign=(
输入:部分,
产出:部分,
关键字:数组
)=>键。减少((acc,elem)=>{
返回{
…acc,
[elem]:1//不安全行为
}
},输出)
您可能已经注意到,assign
函数的返回类型是Partial
,这是不正确的
因此,为了使其完全类型安全,您可以与一起使用,但我认为这将使输出[key]=“B”过于复杂,这也会产生一个错误-类型“B”不能分配给类型“undefined”。在我看来,它更像是一个bug,更像是一个与字符串文本相关的问题。你真的打算定义
B
和D
吗?还是仅仅作为示例?如果是这样,用接口替换它们将解决问题problem@AlonYampolski这是一个非常好的观察!
Type '"B" | "D" | undefined' is not assignable to type 'undefined'.
Type '"B"' is not assignable to type 'undefined'.