Typescript在提取键作为并集时验证所有对象值

问题描述 投票:0回答:1

我正在尝试验证对象文字的值,并同时创建所有键的并集作为函数的参数类型。

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并只键入每个值,例如'one': <PathValue> {prop1: 'foo'},,而这两个都不是非常优雅的解决方案。有没有办法验证整个allPaths对象并从对象文字创建键联合类型?

typescript interface
1个回答
0
投票

您想使用通用函数将const allPaths初始化为1)将type constraintPathDeclaration初始化为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 },
})

Code sample

© www.soinside.com 2019 - 2024. All rights reserved.