如何缩小接受键和值的函数中的值

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

我正在尝试创建一个函数,它可以采用某种类型的键和与该键对应的值。然后当我查看特定的键时我想做一些事情。 我的具体用例是我在 React 中构建的表组件,它迭代对象条目并将键和值传递到单独的函数中,我希望提供安全地覆盖它的能力。

我做了一些简化并实现了这一点。我有 User 类型和一个打印用户详细信息中包含的名称的函数。然而

value.name
并没有被缩小,无法访问。

type User = {
    details: {
        name: string;
    };
    account: {
        status: boolean;
    }
}

const printName =  <K extends keyof User>(key: K, value: User[K]) => {
    if (key === 'details') {
        console.log(value.name); // Doesn't work
    }
}

const user: User = {
    details: {
        name: 'Bob'
    },
    account: {
        status: true
    }
}

printName('details', user.details);

上面的代码产生这种类型的错误:

Property 'name' does not exist on type '{ name: string; } | { status: boolean; }'.
Property 'name' does not exist on type '{ status: boolean; }'.(2339)

Typescript Playground 链接

typescript type-inference type-narrowing
1个回答
0
投票

您需要适当缩小传入密钥的类型,为此,您可以定义一个新类型:

type KeysWithName<T> = keyof {
  [K in keyof T as T[K] extends {name: string} ? K : never]: boolean;
}

然后将函数的签名更新为:

const printName =  <K extends KeysWithName<User>>(key: K, value: User[K]) => {
    if (key === 'details') {
        console.log(value.name); // Doesn't work
    }
}

请注意,这为您提供了函数调用中的类型安全性,这意味着以下操作将引发错误:

printName('details', user.account);

您可以在此处找到完整的工作示例

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