这是一种扁平化(如果我不混淆术语的话)功能。应该用什么代替问号?还是我这样做完全错误?
const array = [{foo: 'val1'}, {bar: 'val2'}]
function flatten <ARRAYOFOBJECTS extends object[]>(array: ARRAYOFOBJECTS): Flat<ARRAYOFOBJECTS> {
// implementation here, does not matter, all that matters is that it returns following:
return {foo: 'val1', bar: 'val2'}
}
type Flat<ARRAYOFOBJECTS> = {
[K in keyof ARRAYOFOBJECTS[????]]: string
}
flatten(array). // at this point IDE should suggest two values: "foo" and "bar"
答案 0 :(得分:1)
您只需声明数组项类型的类型参数,然后将其返回为函数的返回值,由于typescript推断数组类型的方式(对于{ foo: string; bar?: undefined; } | { bar: string; foo?: undefined;})[]
)。但是,要确保正确统一所有联合,我们将需要UnionToIntersection
type UnionToIntersection<U> = (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
const array = [{ foo: 'val1' }, { bar: 'val2' }]
function flatten<T> (array: T[]) : UnionToIntersection<T> {
// implementation here, does not matter, all that matter is that it returns following:
return {foo: 'val1', bar: 'val2'} as any
}
// at this point IDE suggests two values: "foo" and "bar"
flatten(array).bar
flatten(array).foo
修改
使用UnionToIntersection<T>
的原因是因为数组项的类型很大程度上取决于您如何定义数组:
例如:
const array1 = [{foo: 'val1'}, {bar: 'val2'}] // { foo: string; bar?: undefined; } | { bar: string; foo?: undefined;})[]`)
const foo = { foo: 'val1' }
const bar = { bar: 'val2' }
const array2 = [foo, bar]// ({ foo: string; } | { bar: string; })[]
对于array1
打字稿,会将所有对象文字的属性添加到联合中的所有类型,我们在联合的每个成员上都获得了一堆类型为undefined
的额外可选属性({{1} })这就是为什么我们可以访问任何成员,即使它们不在数组的所有项目中也是如此。
对于{ foo: string; bar?: undefined; }
,每个项目的类型都是已知的(即在数组定义之前确定),因此,打字稿不会添加这些额外的属性,因此我们得到了一个没有通用成员的并集作为数组(array2
),我们将无法访问任何成员。