首页 > 解决方案 > 如何从另一条记录的记录中选择

问题描述

我确实有像这样组合的常量和记录类型

const PageType = [
  'type1',
  'type2',
  'type3'
] as const;

export type PageType = typeof PageType[number];

interface PageInfo {
  title: string
}

interface DetailsInfo {
  bla: string;
}


export const Pages: Record<PageType, PageInfo> = {
  type1: {
    title: 't1'
  },
  type2: {
    title: 't2'
  },
  type3: {
    title: 't3'
  }
}

export const Details: Record<PageType, DetailsInfo> = {
  type1: {
    bla: 'bla1',
  },
  type2: {
    bla: 'bla2',
  },
  type3: {
    bla: 'bla2',
  },
};

我想要的是能够做这样的事情Pages[Details.type1].title<-- 返回编译器错误

基本上通过提供一个Details.type1类似的电流Datails["type1"](字符串PageType在那里是动态的)我想得到一个相关的Pages.type1

有任何想法吗?

标签: typescripttypescript-genericstypescript2.0

解决方案


这是我认为您正在尝试实现的参考代码,并且显示了编译器错误。当我第一次阅读您的代码时,我对实例变量的大写名称感到非常困惑,就好像它们是类型一样,所以我已经纠正了这一点。

由于类型擦除,无法理解 DetailsInfo 与其查找键分离后来自哪个条目(如我的示例中的函数定义中所暗示的那样)。如果您希望使用它来控制 javascript 逻辑(例如,使用它来查找和检索某些内容),您需要在运行时保留与任何调用或数据项关联的 PageType 键的信息(即作为 javascript 中的显式值)。

const PAGE_TYPE = [
  'type1',
  'type2',
  'type3'
] as const;

export type PageType = typeof PAGE_TYPE[number];

interface PageInfo {
  title: string
}

interface DetailsInfo {
  bla: string;
}


export const pages: Record<PageType, PageInfo> = {
  type1: {
    title: 't1'
  },
  type2: {
    title: 't2'
  },
  type3: {
    title: 't3'
  }
}

export const details: Record<PageType, DetailsInfo> = {
  type1: {
    bla: 'bla1',
  },
  type2: {
    bla: 'bla2',
  },
  type3: {
    bla: 'bla2',
  },
};

function getPageInfo(detailsInfo:DetailsInfo): PageInfo{
//there is a compiler error here and no known way to implement this function so it returns the 'correct' PageInfo
}

const pageInfo = getPageInfo(details["type1"]);

相比之下,这里是一个可以工作的实现,但您可以看到 PageType 值必须在运行时保留,您希望可以进行查找。我不知道这是否是您实际案例的正确方法,但它表明原始方法缺少什么。

const PAGE_TYPE = [
  'type1',
  'type2',
  'type3'
] as const;

export type PageType = typeof PAGE_TYPE[number];

interface PageInfo<Kind extends PageType> {
  title: string
  kind:Kind
}

interface DetailsInfo<Kind extends PageType> {
  bla: string;
  kind:Kind
}

type PageLookup = {
  [K in PageType]: PageInfo<K>
}

type DetailsLookup = {
  [K in PageType]: DetailsInfo<K>
}

export const pages: PageLookup = {
  type1: {
    kind:"type1",
    title: 't1'
  },
  type2: {
    kind:"type2",
    title: 't2'
  },
  type3: {
    kind:"type3",
    title: 't3'
  }
} as const;

export const details: DetailsLookup = {
  type1: {
    kind:"type1",
    bla: 'bla1',
  },
  type2: {
    kind:"type2",
    bla: 'bla2',
  },
  type3: {
    kind:"type3",
    bla: 'bla2',
  },
} as const;

function getPageTitle<Kind extends PageType>(detailsInfo:DetailsInfo<Kind>): string{
  return pages[detailsInfo.kind].title
}

const pageTitle = getPageTitle(details["type1"]);

推荐阅读