typescript 如何把字面量数组转为联合类型声明?

如果这个字面量数组没有指定类型的话是可以的:

const routes = [
  { path: '/test' }
] as const

type paths = typeof routes[number]['path']

但是如果routes指定了类型(为了书写的时候有语法提示),就不行,paths会推断成string类型:

const routes: RouteRecordRaw[] = [
  { path: '/test' }
] as const

type paths = typeof routes[number]['path']

有什么解决方法吗

解决方法

import type { RouteRecordRaw } from 'vue-router'

type Route<T> = Omit<RouteRecordRaw, 'path'> & { path: T }

function defineRoutes<T extends string>(routes: Route<T>[]) {
  return routes
}

const routes = defineRoutes([
  {
    path: '/contract/index'
  }
])

type paths = typeof routes[number]['path']
阅读 324
avatarAI BotBETA

在 TypeScript 中,当你为一个数组字面量添加明确的类型注解时,它会覆盖数组字面量的原始类型推断。在你的例子中,RouteRecordRaw[] 类型注解覆盖了 routes 数组的字面量类型,导致无法从数组元素中推导出更精确的类型。

要解决这个问题,你可以使用 TypeScript 的泛型来保持数组的原始字面量类型,并在类型注解中使用泛型参数。这样,你可以在保持类型注解的同时,仍然能够从数组元素中推导出精确的类型。

以下是一个示例代码,演示了如何使用泛型来解决这个问题:

// 假设这是你的 RouteRecordRaw 类型
interface RouteRecordRaw {
  path: string;
  // 可能还有其他属性...
}

// 使用泛型来保持原始字面量类型
type LiteralArray<T extends any[]> = {
  [K in keyof T]: T[K] extends infer U[] ? U : never;
}[number];

// 使用泛型来保持原始字面量类型,并添加类型注解
const routes: LiteralArray<[RouteRecordRaw]> = [
  { path: '/test' }
] as const;

// 现在可以从 routes 数组元素中推导出精确的类型
type paths = typeof routes[number]['path']; // 类型为 string

在上面的代码中,LiteralArray 泛型接受一个元组类型 T,并使用映射类型来保持原始字面量类型。然后,在创建 routes 数组时,我们使用 LiteralArray 泛型来保持原始字面量类型,并在类型注解中使用它。这样,paths 类型就能够正确地推导出为 string 类型。

请注意,这种方法只适用于数组字面量,并且数组中的元素类型必须是一致的。如果数组中的元素类型不一致,你可能需要使用其他方法来处理类型推导。

3 个回答

改成泛型,用个函数包一下

interface RouteRecordRaw<T extends string> {
  path: T
}

function defineRoutes<T extends string>(routes: RouteRecordRaw<T>[]) {
  return routes
}

const routes = defineRoutes([
  { path: '/test' },
  { path: '/foo' },
])

type paths = typeof routes[number]['path']

还有一个笨方法,就是用 satisfies 关键字,这个关键字的作用是判断是否符合一个类型并给出类型提示,但其原类型还是你定义的那个类型,可以和 as const 一起用。

interface RouteRecordRaw {
    path: string
}

const _routes = [
    { path: '/test' }
] as const

const routes: readonly RouteRecordRaw[] = _routes

type paths = typeof _routes[number]['path']
logo
Microsoft
子站问答
访问
宣传栏