Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.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:如何转换类型";getter函数的n元组“;输入“;返回值的n元组“;?_Typescript_Types_Typescript Typings - Fatal编程技术网

TypeScript:如何转换类型";getter函数的n元组“;输入“;返回值的n元组“;?

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(

让我们假设您有一个函数,该函数有一个getter函数数组作为输入,并返回一个具有相应返回值的数组(长度相同)

在下面的示例中,类型定义
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”]
正如你所见,它确实起到了作用,但是:

  • 非常难理解
  • 按相反顺序产生结果
  • 当颠倒顺序时,可能会陷入类型实例化过深且可能无限的境地。案例
@jcalz的回答

jcalz在评论中提到可以使用映射的元组类型。如果您不介意一个接一个地传递参数(而不是传递数组),可以这样做:

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