我希望将函数的返回类型设置为元组,其长度与参数数组的长度相同,如果在构建时知道长度的话.否则,返回类型应为布尔array.

第一部分是有效的,但是,当构建时长度未知时,类型是没有任何类型的空元组.

type Tuple<
  T,
  Length extends number,
  Accumulator extends T[] = [],
> = Accumulator["length"] extends Length
  ? Accumulator
  : Tuple<T, Length, [...Accumulator, T]>;

function useHasPermissions<
  const T extends {
    schemaName: string;
    action: string;
  }[],
>(args: { permissions: T }): Tuple<boolean, T["length"]> {
  return [] as any;
}

使用元组(构建时已知的长度)调用:

// const tup: [boolean, boolean, boolean]
const tup = useHasPermissions({
  permissions: [
    {
      schemaName: "User",
      action: "read",
    },
    {
      schemaName: "User",
      action: "create",
    },
    {
      schemaName: "User",
      action: "update",
    },
  ],
});

使用动态数组调用(构建时长度未知):

const arr = useHasPermissions({
  permissions: getAtRuntime(),
});

// Tuple type '[]' of length '0' has no element at index '0'.ts(2493)
// Should be: boolean[]
const a = arr[0];

推荐答案

如果您有一个输入数组类型,并且想要生成一个具有相同一般形状但具有不同元素类型的输出数组类型,则只需使用mapped type即可.映射类型从(泛型)数组类型自动生成数组类型,并从元组类型自动生成元组类型.对于您的示例,它如下所示:

export function useHasPermissions<
  const T extends {
    schemaName: string;
    action: string;
  }[],
>(args: { permissions: T }): { [I in keyof T]: boolean } {
  return [] as any;
}

然后它就可以按预期的那样工作了:

const tup = useHasPermissions({
  permissions: [
    { schemaName: "User", action: "read", },
    { schemaName: "User", action: "create", },
    { schemaName: "User", action: "update", },
  ]
});
// const tup: [boolean, boolean, boolean]

const arr = useHasPermissions({
  permissions:
    getAtRuntime(),
});
// const arr: boolean[]

Playground link to code

Typescript相关问答推荐

类型脚本不会推断键的值类型

ReturnType此索引方法与点表示法之间的差异

TS不推断类型在条件判断后具有属性'

如何推断哪个特定密钥与泛型匹配?

单击并移除for循环中的一项也会影响另一项

为什么我的Set-Cookie在我执行下一次请求后被擦除

对于合并对象中的可选属性(例如选项),类型推断可能是错误的

表单嵌套太深

如何在深度嵌套的Reaction路由对象中隐藏父级?

如何在已知基类的任何子类上使用`extends`?

为什么ESLint会抱怨函数调用返回的隐式`any`?

根据类型脚本中的泛型属性 Select 类型

是否可以强制静态方法将同一类型的对象返回其自己的类?

类型脚本-处理值或返回值的函数

有没有一种更好的方法来存储内存中的数据,而不是在类型脚本中使用数组和基于索引的函数?

有没有一种方法可以提升对象的泛型级别,而对象的值是泛型函数?

为什么我会得到一个;并不是所有的代码路径都返回一个值0;switch 中的所有情况何时返回或抛出?(来自vsCode/TypeScript)

可以';t使用t正确地索引对象;联合;索引类型

为什么过滤器不改变可能的类型?

如何按成员资格排除或 Select 元组?