文字输出推断类型,而不是显式类型 [英] Typescript export inferred type instead of explicit type

查看:29
本文介绍了文字输出推断类型,而不是显式类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的上下文在vue-router中,尽管这可能不重要

我想这样定义我的路线

import { RouteLocationRaw } from 'vue-router'

type RouteNames = 'dashboard' | 'flowRun'
type RouteProperties = Record<RouteNames, (...param:string[]) => RouteLocationRaw>

const Route: RouteProperties = {
    dashboard: () => ({ name: 'dashboard' }),
    flowRun: (flowRunId: string) => ({name: 'flow-run', params: {flowRunId}})
} as const
但是,当我使用它时,我的类型使用的是显式RouteProperties,这实际上比我让TypeScrip推断类型更糟糕。如果我导入路由并键入Routes.flowRun,我看到的参数只有...params:string[],这是有意义的,因为这是我显式定义它的方式。

如果我将我的路线定义为

const Route = {
    dashboard: () => ({ name: 'dashboard' }),
    flowRun: (flowRunId: string) => ({name: 'flow-run', params: {flowRunId}})
} as const

现在,当我导入路由并使用Routes.flowRun时,我的参数使用显式类型命名,如果不提供参数,则不允许我调用。

是否可以在定义新路由时具有我的显式类型的类型安全性,但在使用时仍作为推断类型导出以获得更好的类型安全性?

推荐答案

是,使用标识函数。泛型约束将强制输入值扩展约束,但将返回输入值的实际类型:

TS Playground

import { RawLocation } from 'vue-router';
type RouteLocationRaw = RawLocation;

const routeNames = ['dashboard', 'flowRun'] as const;
type RouteName = typeof routeNames[number];
type RouteProperties = Record<RouteName, (...param:string[]) => RouteLocationRaw>;

function typeSafeRouteProps <T extends RouteProperties>(input: T): {
  [K in keyof T as K extends keyof RouteProperties ? K : never]: T[K]
} {
  const output = {...input};
  for (const key in output) {
    if (!(routeNames as unknown as string[]).includes(key)) {
      delete output[key];
    }
  }
  return output;
}

const Route = typeSafeRouteProps({
  dashboard: () => ({ name: 'dashboard' }),
  flowRun: (flowRunId: string) => ({name: 'flow-run', params: {flowRunId}}),
  test: 123,
});

console.log(Object.keys(Route)); // ['dashboard', 'flowRun']

这篇关于文字输出推断类型,而不是显式类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆