Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript 可以为有区别的联合编写类型安全函数,其中输入是对象,其键是其对应值的区别_Typescript - Fatal编程技术网

Typescript 可以为有区别的联合编写类型安全函数,其中输入是对象,其键是其对应值的区别

Typescript 可以为有区别的联合编写类型安全函数,其中输入是对象,其键是其对应值的区别,typescript,Typescript,是否可以为区分的联合类型编写以下sum函数 第一个arg=标记是一个判别式 第二个arg=对象,其键=鉴别器(应等于值[tag])和值是来自鉴别器并集的形状之一 例如: //如何为成员的键添加限制,使key=A[K][tag] const sum=(标记:T)=>(成员:{[K in keyof A]:A[K]})=>{ // ... 抛出新错误(“”) } 类型形状={kind:'圆';半径:数字}{kind:'正方形';x:number} //应该编译 总和(“种类”)({ 圆:{种类:

是否可以为区分的联合类型编写以下
sum
函数

  • 第一个arg=
    标记
    是一个判别式
  • 第二个arg=
    对象
    ,其
    =
    鉴别器
    (应等于
    值[tag]
    )和
    是来自鉴别器并集的形状之一
例如:

//如何为成员的键添加限制,使key=A[K][tag]
const sum=(标记:T)=>(成员:{[K in keyof A]:A[K]})=>{
// ...
抛出新错误(“”)
}
类型形状={kind:'圆';半径:数字}{kind:'正方形';x:number}
//应该编译
总和(“种类”)({
圆:{种类:'圆',半径:10},
正方形:{种类:'square',x:10}
})
//不应编译,因为平方对其相应值不是正确的判别式
总和(“种类”)({
正方形:{种类:'圆',半径:10},
圆:{种类:'圆',半径:10}
})

是的,可以这样做-但是您需要为联合体提供一个通用类型。如果不为此类型传递参数,则在提供错误属性时TS不可能出错,因为它没有任何可验证的内容

所以看起来像这样:

type StringProperties={[key-in-keyof-O]:O[key]扩展字符串?key:never}[keyof-O];
类型ExtractByTag<
O扩展对象,//要从中提取的对象联合
K扩展StringProperties,//要使用的键
P、 //要提取的属性值
>=O扩展了{[输入K]:P}?O:从来没有;
常量和=(标记:T)=><
O扩展{[key in T]:string},
>(成员:{[key in S[T]]:ExtractByTag})=>{
返回成员;
}
但这并不是很好,因为现在必须显式地优化函数中的类型,以实际执行任何有用的操作,并实现如何执行这些操作,例如:

const isShapesByKey=<
P扩展StringProperties,//“种类”
S扩展{[key in P]:任意}//形状扩展{P:K}
>(key:P,arg:unknown):arg是ShapeKinds=>{
//在这里,您将编写自定义逻辑,以确定成员是否具有某种形状
返回true;
}
常量和=(标记:T)=><
O扩展{[key in T]:string},
>(成员:{[key in S[T]]:ExtractByTag})=>{
if(isShapesByKey(“种类”,成员)){
const circle=members.circle;
const square=members.square;
//用形状做东西
}
返回成员;
}
这完全失去了通用性的好处。在这一点上,您不妨编写一个不太通用、更简单的版本:

type ExtractShape=S扩展了{kind:K}?S:从来没有;
const sum=(成员:{[key in Shape['kind']]:ExtractShape})=>{
const circle=members.circle;
const square=members.square;
}
因此,如果你想走一般路线,我建议你提供一个函数,选择要求和的值。这样,您也可以删除泛型参数,只需为属性选择函数提供一个更简洁的参数:

type StringProperties={[key-in-keyof-O]:O[key]扩展字符串?key:never}[keyof-O];
类型ExtractByTag<
O扩展对象,//要从中提取的对象联合
K扩展StringProperties,//要使用的键
P、 //要提取的属性值
>=O扩展了{[输入K]:P}?O:从来没有;
常量和=(标记:T)=><
O扩展{[key in T]:string},
>(
成员:{[key in O[T]]:ExtractByTag},
属性选择器:(extractFrom:O)=>number
) => {
返回Object.values(成员).reduce((上一个,下一个)=>{
返回上一个+属性选择器(下一个);
}, 0);
})
//用法
总和(“种类”)({
圆:{种类:'圆',半径:10},//确定
square:{kind:'square',x:10},//好的
},(形状:形状)=>{
开关(形状、种类){
案例“循环”:
返回形状。半径;
“方形”案例:
返回形状.x;
}
});
//不应编译,因为平方对其相应值不是正确的判别式
总和(“种类”)({
square:{kind:'square',x:10},//好的
圆:{kind:'circle',x:10},//错误
},(形状:形状)=>{
开关(形状、种类){
案例“循环”:
返回形状。半径;
“方形”案例:
返回形状.x;
}
});

是的,可以这样做-但是您需要为联合体提供一个通用类型。如果不为此类型传递参数,则在提供错误属性时TS不可能出错,因为它没有任何可验证的内容

所以看起来像这样:

type StringProperties={[key-in-keyof-O]:O[key]扩展字符串?key:never}[keyof-O];
类型ExtractByTag<
O扩展对象,//要从中提取的对象联合
K扩展StringProperties,//要使用的键
P、 //要提取的属性值
>=O扩展了{[输入K]:P}?O:从来没有;
常量和=(标记:T)=><
O扩展{[key in T]:string},
>(成员:{[key in S[T]]:ExtractByTag})=>{
返回成员;
}
但这并不是很好,因为现在必须显式地优化函数中的类型,以实际执行任何有用的操作,并实现如何执行这些操作,例如:

const isShapesByKey=<
P扩展StringProperties,//“种类”
S扩展{[key in P]:任意}//形状扩展{P:K}
>(key:P,arg:unknown):arg是ShapeKinds=>{
//在这里,您将编写自定义逻辑,以确定成员是否具有某种形状
返回true;
}
常量和=(标记:T)=><
O扩展{[key in T]:string},
>(成员:{[key in S[T]]:ExtractByTag})=>{
if(isShapesByKey(“种类”,成员)){
const circle=members.circle;
const square=members.square;
//用形状做东西
}
返回成员;
}
这完全失去了通用性的好处。在这一点上,您不妨编写一个不太通用、更简单的版本:

type ExtractShape=S扩展了{kind:K}?S:n