Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.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,我正在尝试为一个函数编写类型,该函数应该将一个对象及其某些键作为参数,并返回一个新对象,其中指定键的值可以是原始值或原始值类型的集合/数组 例如: 如果要传递以下类型的对象: 接口示例{ a:号码 b:号码 c:字符串 } 并将a和c作为键传递,则返回的类型为 { a: number | Set<number> | number[] b: number c: string | Set<string> | string[] } { a:编号|集合

我正在尝试为一个函数编写类型,该函数应该将一个对象及其某些键作为参数,并返回一个新对象,其中指定键的值可以是原始值或原始值类型的集合/数组

例如: 如果要传递以下类型的对象:

接口示例{
a:号码
b:号码
c:字符串
}
并将ac作为键传递,则返回的类型为

{
    a: number | Set<number> | number[]
    b: number
    c: string | Set<string> | string[]
}
{
a:编号|集合|编号[]
b:号码
c:string | Set | string[]
}

我已经通过定义以下类型实现了这一点

type SetOrArray<T, K extends (keyof T)[]> = { [V in K[number]]: Set<T[V]> | T[V][] }
type UnionType<T, K extends (keyof T)[]> = T | SetOrArray<T, K>
type SetOrArray={[V in K[number]]:Set | T[V][]
类型UnionType=T | SetOrArray

但是,当我对一个对象尝试此操作时,结果UnionType中只保留传递的键(在K中),其余的键(由于T |union,这些键应该与它们的原始类型一起出现)在UnionType上不存在

例如:

function afunc<T, K extends (keyof T)[])>(obj: T, ...keys: K): UnionType<T, K> {
    return obj // just for example
}

const obj = {a: 1, b: 2, c: "apple"}
const res = afunc(obj, "a", "c")
// res.a exists with type number | Set<number> | number[]
// res.c exists with type string | Set<string> | string[]
// but res.b does not exist, whereas it should have had type number
函数afunc(对象:T,…键:K):UnionType{
return obj//仅作为示例
}
const obj={a:1,b:2,c:“苹果”}
常数res=afunc(obj,“a”、“c”)
//res.a以类型编号| Set | number[]存在
//res.c存在,类型为string | Set | string[]
//但是res.b不存在,而它应该有类型号

我刚刚为缺少的字段添加了一个附加类型,请尝试以下代码:

interface Example {
    a: number
    b: number
    c: string
}

type SetOrArray<T, K extends (keyof T)[]> = { [V in K[number]]: T[V] | Set<T[V]> | T[V][] }
//Use exclude to create object with missing field  
type Outersect<T, K extends (keyof T)[]> = { [P in Exclude<keyof T, keyof SetOrArray<T, K>>]: T[P] }
//And union with SetOrArray type
type UnionType<T, K extends (keyof T)[]> = Outersect<T, K> & SetOrArray<T, K>

function afunc<T, K extends (keyof T)[]>(obj: T, ...keys: K): UnionType<T, K> {
    return obj // just for example
}


const obj = { a: 1, b: 2, c: "apple" }
const res = afunc(obj, "a", "c")

const test1 = res.a;
const test2 = res.b;
const test3 = res.c;
接口示例{
a:号码
b:号码
c:字符串
}
键入SetOrArray={[V in K[number]]:T[V]| Set | T[V][]
//使用“排除”创建缺少字段的对象
类型outerSet={[P in Exclude]:T[P]}
//与SetOrArray类型的并集
类型UnionType=Outersect和SetOrArray
函数afunc(对象:T,…键:K):UnionType{
return obj//仅作为示例
}
const obj={a:1,b:2,c:“苹果”}
常数res=afunc(obj,“a”、“c”)
常数test1=res.a;
常数test2=res.b;
常数test3=res.c;

我找到了这个问题的答案,这与 AleksandreJavakhishvili做了以下工作,只是工作得更好,更简洁

它是通过使用条件类型来完成的


//如果V也存在于K中,则创建union类型,否则为原始值类型
类型UnionType={
[V在keyof T]:(V扩展K?集| T[V][]T[V]:T[V])
}
函数afunc(对象:T,…键:K):UnionType{
return obj//仅作为示例
}
const obj={a:1,b:2,c:“苹果”}
常数res=afunc(obj,“a”、“c”)
常数test1=res.a;
常数test2=res.b;
常数test3=res.c;

谢谢你的工作。我还发现了一种更简洁的方法,使用条件类型。你可以检查我的答案。