我有以下代码:
appendTo="@(body)"
此结构允许我将新条目添加到export const myRecord = {
Entry1: {
title: 'hey ho',
data: {
version: 1,
valid: true
}
},
Entry2: {
title: 'hey hey',
data: {
version: 2,
valid: false
}
}
} as const;
export type MyRecordsIds = keyof typeof myRecord;
export function doSomething(recordId: MyRecordsIds){
//does something
}
,而无需将它们显式添加到myRecord
。
反过来,MyRecordIds
类型允许我在代码中限制这些ID。
到目前为止,一切都很好。但是现在我想将MyRecordsIds
中的值限制为某种类型,例如:
myRecord
最明显的解决方法是:
export interface Entry {
title: string;
data: {
version: number;
valid: boolean;
}
}
该限制有效,但我放弃了对export const myRecord: Record<string, Entry> = {
Entry1: {
title: 'hey ho',
data: {
version: 1,
valid: true
}
},
Entry2: {
title: 'hey hey',
data: {
version: 2,
valid: false
}
}
};
类型的限制(由于MyRecordsIds
,它变为string
)。
我到目前为止得到的最接近的是:
Record<string,Entry>
这同时限制了记录条目和ID,这意味着在以下情况下构建会失败:
const myRecord = {
Entry1: {
title: 'hey ho',
data: {
version: 1,
valid: true
}
},
Entry2: {
title: 'hey hey',
data: {
version: 2,
valid: false
}
}
} as const;
type MyRecordsIds = keyof typeof myRecord;
export const myRecordTyped: Record<MyRecordsIds, Entry> = myRecord;
与不是记录中键的某些字符串一起使用。doSomething
类型的条目。但是,这种方法有一个严重的缺点。如果其中一项输入错误,则构建将在分配时失败(而不是指向记录中有问题的行),这将使得难以跟踪问题:
Entry
在保持对记录条目类型和记录ID的限制的同时,是否有更好的方法来实现此行为?
答案 0 :(得分:3)
也许您只是希望一个辅助函数可以让您定义myRecord
,使其可以接受任何键,但将值限制为Entry
:
const asMyRecord = <T extends Record<keyof T, Entry>>(t: T): Record<keyof T, Entry> => t;
您将像这样使用它:
export const myRecord = asMyRecord({
Entry1: {
title: 'hey ho',
data: {
version: 1,
valid: true
}
},
Entry2: {
title: 'hey hey',
data: {
version: 2,
valid: false
}
}
});
如果您尝试将任何属性值设置为不可分配给Entry
的内容,则会收到错误消息:
const badMyRecord = asMyRecord({
EntryNope: {
title: 123, // error! number is not strng
data: {
version: "one", // error! string is not number
valid: false
}
}
})
已知MyRecord
像以前一样具有特定的文字键:
type MyRecordsIds = keyof typeof myRecord; // "Entry1" | "Entry2"
因此,它应该保持合理的强类型(当前asMyRecord
最终会产生类型为Record<keyof T, Entry>
的值):
myRecord.Entry2.title = "okay"; // okay
myRecord.Entry2.oops = false; // error! "oops" doesn't exist on Entry
myRecord.Entry3.title = "nope"; // error! "Entry3" not "Entry1" | "Entry2"
好的,希望能有所帮助;祝你好运!
答案 1 :(得分:0)
我能得到的最接近的结果是将每个条目分配给键入常量
export interface Entry {
title: string
data: {
version: number
valid: boolean
}
}
const Entry1: Entry = {
title: 'hey ho',
data: {
version: 1,
valid: true
}
}
const Entry2: Entry = {
title: 'hey hey',
data: {
version: 2,
valid: false
}
}
const myRecord = {
Entry1,
Entry2
}
type MyRecordsIds = keyof typeof myRecord
export const myRecordTyped: Record<MyRecordsIds, Entry> = myRecord