我正在尝试创建一个函数,它可以采用某种类型的键和与该键对应的值。然后当我查看特定的键时我想做一些事情。 我的具体用例是我在 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)
您需要适当缩小传入密钥的类型,为此,您可以定义一个新类型:
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);
您可以在此处找到完整的工作示例。