将 ...args 映射到子类型的元组
Mapping ...args to tuple of child type
我有一个场景,我想要一个可以接受通用对象的任意数量参数的函数。
我想要结果 return 一个元组,其中此对象的每个通用参数都是元组位置类型。
例子
type Wrap<T> = {
obj: T;
}
function UnWrap<T extends Array<Wrap<One|Two>>>(...args:T){ //return type?
return args.map(i => i.obj);
}
type One = {
foo: string;
}
type Two = {
bar: string;
}
let one: Wrap<One> = {obj: {foo: 'abc'}}
let two: Wrap<Two> ={obj: {bar: 'abc'}}
// res type should be [One, Two, Two, One]
let res = UnWrap(one, two, two, one)
如果我只是 return 传入的确切类型,我就能让类型工作:
function ReturnSelf<T extends Array<Wrap<One|Two>>>(...args:T): typeof args{
return args;
}
但我不确定如何索引 ['obj']
类型。我想也许可以使用映射类型来做到这一点,但我不太明白。
是的,自从 TypeScript 3.1 引入 the ability to map tuple/array types 以来,您就可以使用映射类型来执行此操作。你可以用 "forward" 的方式来做,就像你在做的那样:
function UnWrap<T extends Array<Wrap<One | Two | Three>>>(...args: T) {
return args.map(i => i.obj) as {
[K in keyof T]: T[K] extends Wrap<infer U> ? U : never
};
}
let res2 = UnWrap(one, two, three, two); // [One, Two, Three, Two]
或 "reverse" 方式,使用 inference from mapped types:
function UnWrap2<T extends Array<One | Two | Three>>(
...args: { [K in keyof T]: Wrap<T[K]> }
) {
return args.map(i => i.obj) as T;
}
let res3 = UnWrap2(one, two, three, two); // [One, Two, Three, Two]
任何一种方法都行得通,如您所见...无论哪种方法,编译器都无法理解 args.map(i => i.obj)
执行您正在执行的类型操作,因此您需要使用 type assertion or the equivalent of one (such as using a single overload 签名)。
好的,希望对您有所帮助。祝你好运!
我有一个场景,我想要一个可以接受通用对象的任意数量参数的函数。
我想要结果 return 一个元组,其中此对象的每个通用参数都是元组位置类型。
例子
type Wrap<T> = {
obj: T;
}
function UnWrap<T extends Array<Wrap<One|Two>>>(...args:T){ //return type?
return args.map(i => i.obj);
}
type One = {
foo: string;
}
type Two = {
bar: string;
}
let one: Wrap<One> = {obj: {foo: 'abc'}}
let two: Wrap<Two> ={obj: {bar: 'abc'}}
// res type should be [One, Two, Two, One]
let res = UnWrap(one, two, two, one)
如果我只是 return 传入的确切类型,我就能让类型工作:
function ReturnSelf<T extends Array<Wrap<One|Two>>>(...args:T): typeof args{
return args;
}
但我不确定如何索引 ['obj']
类型。我想也许可以使用映射类型来做到这一点,但我不太明白。
是的,自从 TypeScript 3.1 引入 the ability to map tuple/array types 以来,您就可以使用映射类型来执行此操作。你可以用 "forward" 的方式来做,就像你在做的那样:
function UnWrap<T extends Array<Wrap<One | Two | Three>>>(...args: T) {
return args.map(i => i.obj) as {
[K in keyof T]: T[K] extends Wrap<infer U> ? U : never
};
}
let res2 = UnWrap(one, two, three, two); // [One, Two, Three, Two]
或 "reverse" 方式,使用 inference from mapped types:
function UnWrap2<T extends Array<One | Two | Three>>(
...args: { [K in keyof T]: Wrap<T[K]> }
) {
return args.map(i => i.obj) as T;
}
let res3 = UnWrap2(one, two, three, two); // [One, Two, Three, Two]
任何一种方法都行得通,如您所见...无论哪种方法,编译器都无法理解 args.map(i => i.obj)
执行您正在执行的类型操作,因此您需要使用 type assertion or the equivalent of one (such as using a single overload 签名)。
好的,希望对您有所帮助。祝你好运!