TypeScript:如何转换类型";getter函数的n元组“;输入“;返回值的n元组“;?
让我们假设您有一个函数,该函数有一个getter函数数组作为输入,并返回一个具有相应返回值的数组(长度相同) 在下面的示例中,类型定义TypeScript:如何转换类型";getter函数的n元组“;输入“;返回值的n元组“;?,typescript,types,typescript-typings,Typescript,Types,Typescript Typings,让我们假设您有一个函数,该函数有一个getter函数数组作为输入,并返回一个具有相应返回值的数组(长度相同) 在下面的示例中,类型定义type ValueTupleOf=…的外观如何 function getValues any)[]>(getter:A):ValueTupleOf{ 返回getter.map(getter=>getter()) } 编辑:当然我可以这样做,但我希望有更好的解决方案: 函数getValues(getter:[()=>A1]):[A1] 函数getValues(
type ValueTupleOf=…
的外观如何
function getValues any)[]>(getter:A):ValueTupleOf{
返回getter.map(getter=>getter())
}
编辑:当然我可以这样做,但我希望有更好的解决方案: 函数getValues(getter:[()=>A1]):[A1] 函数getValues(getter:[()=>A1,()=>A2]):[A1,A2] 函数getValues(getter:[()=>A1,()=>A2,()=>A3]):[A1,A2,A3] // ... 等 函数getValues(getter:any):any{ 返回getter.map(getter=>getter()) }
简短回答 坚持使用重载。一开始他们可能会做很多工作,但另一种情况更糟 长答案 TypeScript没有可变类型,因此为了保持元组的顺序,必须使用技巧。然而,这种伎俩丑陋且有局限性
import { Reverse } from 'typepark';
type Thunk<T> = () => T;
type ReturnTypesOf<T extends Thunk<any>[], Length extends number = T['length'], Queue extends any[] = [], Index extends number = Queue['length']> = {
done: Queue;
next: ReturnTypesOf<T, Length, Prepend<ReturnType<T[Index]>, Queue>>;
}[Yield<Queue, Length>];
type Yield<Queue extends any[], Length extends number> =
Queue['length'] extends Length
? 'done'
: 'next';
type Prepend<T, U extends any[]> =
((head: T, ...tail: U) => void) extends ((...all: infer V) => void)
? V
: [];
type T1 = ReturnTypesOf<[() => 1, () => 'foo']>; // ["foo", 1]
type T2 = Reverse<T1>; // [1, "foo"]
从“typepark”导入{Reverse};
类型Thunk=()=>T;
类型ReturnTypesOf={
完成:队列;
下一步:返回类型;
}[收益率];
类型产量=
队列['length']扩展长度
? '完成
:“下一步”;
类型前置=
((头部:T,…尾部:U)=>void)扩展((…全部:推断V)=>void)
? v
: [];
类型T1=返回类型1,()=>“foo']>;//[“foo”,1]
T2型=反向;//[1,“foo”]
正如你所见,它确实起到了作用,但是:
- 非常难理解
- 按相反顺序产生结果
- 当颠倒顺序时,可能会陷入类型实例化过深且可能无限的境地。案例
type AnyFunction = () => any;
/**
* Mapped type, but for tuples.
*/
type ReturnTypesOf<T extends AnyFunction[]> = {
[K in keyof T]: T[K] extends AnyFunction
? ReturnType<T[K]>
: never
};
function getValues<T extends AnyFunction[]>(...functions: T) {
return functions.map(callback => callback()) as ReturnTypesOf<T>;
}
const values = getValues(
() => "foo",
() => 42
)
type AnyFunction=()=>any;
/**
*映射类型,但用于元组。
*/
类型ReturnTypesOf={
[K in keyof T]:T[K]扩展了任意函数
?返回式
:从不
};
函数getValues(…函数:T){
返回functions.map(callback=>callback())作为ReturnTypesOf;
}
const values=getValues(
()=>“福”,
() => 42
)
给你。。。(不言自明)还有
类型返回类型={
[K in keyof T]:T[K]扩展(…args:any[])=>推断R?R:never
}
类型Getter=()=>T;
函数getValues(getter:getter){
返回getter.map(getter=>getter())
}
让value=getValues(“a1”、()=>“a2”]>[()=>“a1”、()=>“a2”])
/*值的类型为[“a1”、“a2”](悬停以检查)
在最新的TS版本中,您可以使用它生成元组,
而不是像我在这里那样写两遍
*/
foo类型=返回类型“a1”,()=>“a2”]>;
//foo是[“a1”,“a2”]
getValues(“a1”]>[(x:string)=>“a1”])
//另外,键入safe^会导致错误
TS3.1介绍,仅供参考。谢谢!没错。但是,当参数是原始API假定的数组(而不是参数列表)时,我无法让它们工作。是的,这很奇怪,但是如果在约束中包含元组类型,则可以说服编译器将数组推断为元组,如函数getValues(functions:t){return functions.map(callback=>callback())与返回类型相同;}
。这是一些篮球跳跃,但它确实如预期的那样有效。
type ReturnTypes<T> = {
[K in keyof T]: T[K] extends (...args: any[]) => infer R ? R : never
}
type Getter<T = {}> = () => T;
function getValues<Getters extends Array<Getter>>(getters: Getters) {
return <ReturnTypes<Getters>>getters.map(getter => getter())
}
let values = getValues(<[() => "a1", () => "a2"]>[() => "a1", () => "a2"])
/* type of values is ["a1", "a2"] (hover to check)
In latest TS version you can use <const> to make tuples,
instead of writing things twice like I did here
*/
type foo = ReturnTypes<[() => "a1", () => "a2"]>;
// foo is ["a1", "a2"]
getValues(<[(x: string) => "a1"]>[(x: string) => "a1"])
// Also type-safe ^ gives error