打字稿:推断嵌套 keyof 属性的类型 [英] Typescript: Infer type of nested keyof Properties

查看:22
本文介绍了打字稿:推断嵌套 keyof 属性的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想定义一个数组类型,它必须包含给定类型的嵌套属性名称链.

I want to define an Array type that must contain a chain of nested property names of a given type.

假设我有一个类型:

    type Foo = {
        outer: {
            inner: any;
        }
    }

现在我想定义一个包含 2 个元素的数组类型:

Now I want to define an Array type with 2 elements:

type PropertyList<T, K1 extends keyof T, K2 extends keyof T[K1]> = [K1, K2];

我想这样使用它:

let myList:PropertyList<Foo> = ["outer", "inner"]

所以我希望编译器检查包含的 2 个属性名称是否是 Foo 的嵌套属性名称.

So I want the compiler to check if the 2 contained Property names are nested property names of Foo.

但是我不能只用 1 个泛型参数定义 PropertyList,然后我得到这个错误:

But I can't define PropertyList with only 1 generic parameter, I get this error then:

TS2314: Generic type 'PropertyList' requires 3 type argument(s)

知道如何推断嵌套的 keyof 类型而不必指定它们吗?

Any idea how i can infer the nested keyof types without having to specify them?

推荐答案

Tao 的回答中给出了如何做到这一点的第一个近似值,问题是如果添加更多属性,它不会按预期工作:

A first approximation of how to do this is in Tao's answer, the problem is that if you add more properties it does not work as expected:

type Foo = {
    outer: {
        inner: any;
    }
    outer2: {
        inner2: any;
    }
}

type PropertyList<T, K1 extends keyof T = keyof T, K2 extends keyof T[K1] = keyof T[K1]> = [K1, K2];

let myList:PropertyList<Foo> = ["outer", "inner"] // error, since K2 will have to be a property of both outer and outer2

您可以使用函数来帮助根据传递的实际参数推断出正确类型.我们需要使用两个函数的方法,因为我们需要为 TK1K2 提供通用参数,但我们只想指定 T 如果我们指定一个,我们必须指定所有参数:

You can use function to help with inferring the corect type based on the actual parameters passed. We need to use a two function approach because we need to have generic parameters for T, K1 and K2, but we only want to specify T and if we specify one we must specify all parameters:

function pathFor<T>() {
    return  function <K1 extends keyof T, K2 extends keyof T[K1]>(outer: K1, inner: K2): [K1,K2]{
        return  [outer, inner];
    }
}
// Usage 
let myList = pathFor<Foo>()("outer", "inner"); // typed as ["outer, "inner"]
let myList2 = pathFor<Foo>()("outer2", "inner"); // error, inner is not part of outer2
let myList3 = pathFor<Foo>()("outer2", "inner2"); // typed as ["outer2, "inner2"]

编辑

您还可以扩展该函数以获取最长为有限长度的路径(示例中为 4,但根据需要添加更多):

You can also expand the function to take paths up to a finite length (4 in the example, but add more as needed):

function keysFor<T>() {
    function keys<K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2], K4 extends keyof T[K1][K2][K3]>(outer: K1, inner: K2, innerInner: K3, innerInnerInner: K4): [K1,K2, K3, K4]
    function keys<K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(outer: K1, inner: K2, innerInner: K3): [K1,K2, K3]
    function keys<K1 extends keyof T, K2 extends keyof T[K1]>(outer: K1, inner: K2): [K1,K2]
    function keys(): string[]{
        return [...arguments];
    }
    return keys
}

这篇关于打字稿:推断嵌套 keyof 属性的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆