要求子对象属性值与父键类型相同

时间:2018-12-15 16:07:38

标签: typescript

在TypeScript中,是否可以使用索引签名来强制执行以下结构?

{
    a: { name: 'a' }, // Valid
    b: { name: 'b' }, // Valid
    c: { name: 'd' } // Error: Type '"d"' is not assignable to type '"c"'.
}

该对象可以使用任意字符串键接受任意数量的属性,但要求每个属性的值是一个对象,该对象本身具有可选的“ name”属性,该属性的值必须是该对象的键在父对象中分配。

可以使用字符串联合类型实现类似的功能,如下所示。但是,尚不清楚如何扩展它以将键接受为任何字符串。

type MethodNameVariant = 'GET' | 'PATCH' | 'POST' | 'DELETE';
type Methods =
{
    [MethodName in MethodNameVariant]?: Method <MethodName>
};
interface Method
{
    name?: MethodName;
}

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:0)

由于string具有无限域,并且不能轻易地用文字类型的并集表示,例如boolean {{3 }}。 TypeScript甚至没有尝试像在can中对字符串文字的并集那样对string进行迭代;如果尝试这样做,最终将得到类型太宽的{[k: string]: {name: string}

我最接近所需行为的方法是创建一个mapped types辅助函数,以检查您提供的任何对象类型的键,然后在这些键上进行映射。像这样:

const asMyType = <T extends { [K in keyof T]: { name: K } }>(t: T) => t;

因此asMyType()仅返回其参数,但仅接受与您的约束匹配的参数。

const okay = asMyType({
  a: { name: "a" },
  b: { name: "b" },
  c: { name: "c" }
})

const notOkay = asMyType({
  a: { name: 'a' }, // Valid
  b: { name: 'b' }, // Valid
  c: { name: 'd' } // Error: Type '"d"' is not assignable to type '"c"'.
})

好,那是您想要的错误!这里的主要缺点是T extends {[K in keyof T]: ...构造不像普通的旧类型那样容易处理,因为它依赖于泛型类型参数推断,但是取决于您的用例,它可能会起作用。

希望有帮助。祝你好运!