javascript - Typescript:使用 .map 时如何保留长度信息

标签 javascript arrays typescript tuples type-inference

我目前的“工作”方法是这样的:

const generateMainOrientations = <T extends readonly string[]>(
  mainOrientationsNames: T
): { [Index in keyof T]: Orientation } => {
  const temp: Orientation[] = mainOrientationsNames.map(
    mainOrientationName => ({
      name: mainOrientationName,
      getYear(date) {
        return date.getFullYear()
      },
      getRecordContent: getMainOrientationRecordContent
    })
  )

  return temp as unknown as { [Index in keyof T]: Orientation }
}

const mainOrientations = generateMainOrientations([
  "One",
  "Two",
  "Three"
] as const)

但是,我必须使用 as unknown as { [Index in keyof T]: Orientation } ,这并不理想,否则(即使从 temp 变量中删除类型断言)它也会抛出

Type '{ name: string; getYear(date: any): any; getRecordContent: (values: number[]) => string[]; }[]' is not assignable to type '{ [Index in keyof T]: Orientation; }'.ts(2322)

仍然,{ name: string; getYear(date: any): any; getRecordContent: (values: number[]) => string[]; }Orientation 的定义

这表明在使用 map 后任何长度信息都丢失了。

有没有更有机的方法来实现这一点,最好根本不必使用类型断言,或者至少不必使用 as unknown .目标是使 mainOrientations 成为 Orientation 的元组与传递给 generateMainOrientations 的参数长度相同, 所以 [Orientation, Orientation, Orientation]在这种情况下,(不是 Orientation[] )。

Playground

最佳答案

你需要重载你的函数:

interface Orientation {
  name: string,
  getYear(date: Date): number,
  getRecordContent(values: number[]): string[]
}

declare function getMainOrientationRecordContent(values: number[]): string[]

function generateMainOrientations<T extends string, Tuple extends T[]>(
  mainOrientationsNames: [...Tuple]
): { [Index in keyof Tuple]: Orientation }
function generateMainOrientations(
  mainOrientationsNames: string[]
) {
  return mainOrientationsNames.map(
    mainOrientationName => ({
      name: mainOrientationName,
      getYear: (date: Date) => date.getFullYear(),
      getRecordContent: getMainOrientationRecordContent
    })
  )
}

// [Orientation, Orientation, Orientation]
const mainOrientations = generateMainOrientations([
  "One",
  "Two",
  "Three"
])

Playground

请记住,一旦您使用了 Array.prototype.map , typescript 就不会保留结果的长度。 Here你可以找到原因。

因此,您只有两个选择:重载和类型断言。

如果将 name 属性参数化,您可以做得更好:

interface Orientation<Name extends string> {
  name: Name,
  getYear(date: Date): number,
  getRecordContent(values: number[]): string[]
}

declare function getMainOrientationRecordContent(values: number[]): string[]

function generateMainOrientations<T extends string, Tuple extends T[]>(
  mainOrientationsNames: [...Tuple]
): { [Index in keyof Tuple]: Orientation<Tuple[Index] & string> }
function generateMainOrientations(
  mainOrientationsNames: string[]
) {
  return mainOrientationsNames.map<Orientation<string>>(
    name => ({
      name,
      getYear: (date) => date.getFullYear(),
      getRecordContent: getMainOrientationRecordContent
    })
  )
}

// [Orientation<"One">, Orientation<"Two">, Orientation<"Three">]
const mainOrientations = generateMainOrientations([
  "One",
  "Two",
  "Three"
])

关于javascript - Typescript:使用 .map 时如何保留长度信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71107948/

相关文章:

javascript - 页面上具有相同的小部件多次发生时间/变量冲突

javascript - 从 ejs View 获取 JSON 数据到 Controller

在 C 中动态分配的数组上调用 free() 似乎正在更改存储在另一个数组中的数据?

javascript - TypeScript 在 WebStorm 7 中将所有 ts 文件编译为单个 JavaScript 文件

javascript - 如何选择字符串的一部分?

javascript - 动态位置后的粘性标题

arrays - 合并排序变体 n+m,困惑

c# - 自引用属性数组

reactjs - 使用两个不同的 prop 接口(interface) React TypeScript 组件

javascript - 使用 JavaScript 或 TypeScript 使用react?