Typescript 如何从另一条记录重新记录中进行选择

Typescript 如何从另一条记录重新记录中进行选择,typescript,typescript-generics,typescript2.0,Typescript,Typescript Generics,Typescript2.0,我确实有常数和记录类型这样组合 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

我确实有常数和记录类型这样组合

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',
  },
};
const页面类型=[
“类型1”,
“类型2”,
“类型3”
]作为常量;
导出类型PageType=页面类型的类型[编号];
界面页面信息{
标题:字符串
}
接口详细信息信息信息{
bla:字符串;
}
导出常量页:记录={
类型1:{
标题:“t1”
},
类型2:{
标题:“t2”
},
类型3:{
标题:“t3”
}
}
导出常量详细信息:记录={
类型1:{
布拉:“布拉1”,
},
类型2:{
布拉:“布拉2”,
},
类型3:{
布拉:“布拉2”,
},
};

我想做的是能够像
Pages[Details.type1].title这样的操作,这是我认为您正在尝试实现的、显示编译器错误的参考代码。当我第一次阅读您的代码时,我对实例变量被赋予大写的名称感到非常困惑,就好像它们是类型一样,所以我已经纠正了这一点

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

const页面类型=[
“类型1”,
“类型2”,
“类型3”
]作为常量;
导出类型PageType=页面类型\类型[编号];
界面页面信息{
标题:字符串
}
接口详细信息信息信息{
bla:字符串;
}
导出常量页:记录={
类型1:{
标题:“t1”
},
类型2:{
标题:“t2”
},
类型3:{
标题:“t3”
}
}
导出常量详细信息:记录={
类型1:{
布拉:“布拉1”,
},
类型2:{
布拉:“布拉2”,
},
类型3:{
布拉:“布拉2”,
},
};
函数getPageInfo(detailsInfo:detailsInfo):PageInfo{
//这里有一个编译器错误,并且没有实现此函数的已知方法,因此它返回“正确”的PageInfo
}
const pageInfo=getPageInfo(详细信息[“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"]);
const页面类型=[
“类型1”,
“类型2”,
“类型3”
]作为常量;
导出类型PageType=页面类型\类型[编号];
界面页面信息{
标题:字符串
种类:种类
}
接口详细信息信息信息{
bla:字符串;
种类:种类
}
类型PageLookup={
[K in PageType]:页面信息
}
类型DetailsLookup={
[K in PageType]:详细信息信息信息
}
导出常量页面:页面查找={
类型1:{
种类:“类型1”,
标题:“t1”
},
类型2:{
种类:“type2”,
标题:“t2”
},
类型3:{
种类:“type3”,
标题:“t3”
}
}作为常量;
导出常量详细信息:DetailsLookup={
类型1:{
种类:“类型1”,
布拉:“布拉1”,
},
类型2:{
种类:“type2”,
布拉:“布拉2”,
},
类型3:{
种类:“type3”,
布拉:“布拉2”,
},
}作为常量;
函数getPageTitle(detailsInfo:detailsInfo):字符串{
返回页面[detailsInfo.kind]。标题
}
const pageTitle=getPageTitle(详细信息[“type1”]);

getPageInfo
是不是需要实现一些东西?试着填补你原始帖子的空白,这就是你想知道如何实现的功能,对吧?我是说,根据这个定义,没有可能实现。相比之下,如果您有getPageInfo(pageType:pageType,lookup:Record=pages)签名(例如pageType是可访问的实际值)然后你就可以做了。这是否意味着我想要实现的是一个坏主意?不,这只是意味着你需要重新构造你的方法,以确保javascript运行时能够访问你想要用于查找的信息。这不能用你尝试的方式来完成。
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"]);