我正在尝试验证对象文字的值,同时创建所有键的并集作为函数的参数类型。
interface PathValue {
prop1: string;
prop2?: number;
}
interface PathDeclaration {
[key: string]: PathValue;
}
const allPaths: PathDeclaration = {
'one': {prop1: 'foo'},
'two': {prop1: 'bar', prop2: 2},
}
function getItem(path: Extract<keyof typeof allPaths, string>) {
return allPaths[path];
}
此示例的问题在于,由于PathDeclaration是allPath的类型,并且其键只是通用字符串,因此我的path
参数无法再从对象文字中推断出键。
我能想到的唯一解决方案是必须在单独的接口中声明所有键(重复代码),或者代替键入allPaths,我可以删除PathDeclaration
并仅键入{{1 }}都不是非常优雅的解决方案。有没有办法验证整个'one': <PathValue> {prop1: 'foo'},
对象并从对象文字创建键联合类型?
答案 0 :(得分:1)
您要使用通用函数将const allPaths
初始化为1)将type constraint PathDeclaration
和进行添加2)让TS infer为给定值对象文字类型自动生成。只有函数可以一步完成此操作。
const createPaths = <T extends PathDeclaration>(pd: T) => pd
const allPaths = createPaths({
'one': { prop1: 'foo' },
'two': { prop1: 'bar', prop2: 2 },
})
/*
{
one: { prop1: string; };
two: { prop1: string; prop2: number; };
}
*/
以上将捕获错误:
const allPathsError = createPaths({
'one': { prop3: 'foo' }, // error
'two': { prop1: 'bar', prop2: "bar" }, // error
})
并推断所有键:
// path: "one" | "two"
function getItem(path: Extract<keyof typeof allPathsInline, string>) {
return allPathsInline[path];
}
这也是我喜欢使用IIFE使事情变得苗条的少数情况之一:
const allPathsInline = (<T extends PathDeclaration>(pd: T) => pd)({
'one': { prop1: 'foo' },
'two': { prop1: 'bar', prop2: 2 },
})