具有特定叶类型的嵌套对象的类型

Type for nested objects with specific leaf types

我想要嵌套对象的类型,它们的叶子有特定类型。

我希望这是正确的:

let a: Leaves<number> = {
    "foo": 1,
    "bar": {
        "baz": 2
    }
};

这失败了:

let a: Leaves<number> = {
    "foo": 1,
    "bar": {
        "baz": 'something else' // Leaf of type string
    } 
};

我试过了

export type Leaves<T> = {
    [P in keyof T]: T | Leaves<T>;
}

然而,使用该定义,两个示例都给出了编译错误。第一个说 Type '{ "foo": number; "bar": number; }' is not assignable to type 'number'.

有办法解决这个问题吗?

如果您需要一个具有任意键的节点类型,以及叶节点或其他节点的值,indexable type 是可行的方法:

export type Leaves<T> = {
    [n: string]: T | Leaves<T>
}

(顺便说一句,我宁愿称它为 Node<T>,而不是 Leaves<T>

这里不适合映射类型,因为这样的映射类型

{
    [P in keyof T]: T | Leaves<T>;
}

只能拥有 T 拥有的属性——这就是 [P in keyof T]: 所说的。当 Tnumber 时,这意味着映射类型只能具有 number 类型中的属性,并且因为 number 是原始类型,所以它本质上意味着它与 number。这就是 not assignable to number 错误消息的原因 - 打字稿试图找到最具描述性的类型以显示在错误消息中,在您的情况下它只是 number.