Typescript:是否可以强制 'keyof T' 为字符串?

3

我有一个函数的类型如下:

const getByPrimaryKey = <E>(list: E[], primaryKey: keyof E): E => {...} 

我可以为与primaryKey相关联的值添加类型验证吗?例如:

interface User {
  id: string
  name?: string
  age: number
}

const users: User[] = [{id: '1', age: 1}]

getByPrimaryKey<User>(users, 'id') // OK since id is a string
getByPrimaryKey<User>(users, 'name') // NOT OK because name maybe undefined
getByPrimaryKey<User>(users, 'age') // NOT OK because age is a number



在这种情况下,keyof T 将是 'id' | 'name' | 'age',它们都是字符串;我认为你的意思是想要一个关联值类型为 string 的键。因此,你需要从这个 Q&A 中获取 KeysMatching 类型:如何编写 PickByValue 类型? - kaya3
我更新了我的问题以使其更清晰。我在谈论值的类型。 我刚刚回答了自己的问题。 - Alexandre Annic
2
我没有看到你的问题和你自己对它的回答之间有任何关系。通过添加第二个类型参数,您会破坏提供一个类型参数的用例示例,并且您的类型参数 PK 仅受 keyof E 的限制,因此没有任何阻止它成为 'name''age' - kaya3
你说得对。我的原始问题已经忘记了,我发布了一个在我的实际情况下有效的解决方案。谢谢你提醒我。 - Alexandre Annic
为什么 getByPrimaryKey<User>(users, 'age') // NOT OK because age is a number 不行? - captain-yossarian from Ukraine
由于我将在对象中使用索引primaryKey,因此我不希望选取的属性是除字符串以外的其他内容(例如未定义或子对象)。 - Alexandre Annic
1个回答

4
你需要结合几个条件类型
要获取所有非可选的键:
type RequiredKeys<T> = { [K in keyof T]-?: ({} extends { [P in K]: T[K] } ? never : K) }[keyof T];

获取所有具有特定值类型的键:
type TypeMatchingKeys<T, V> = { [K in keyof T]: T[K] extends V ? K : never }[keyof T];

然后您可以使用两者的交集:
type NonOptionalTypeMatchingKeys<T, V> = TypeMatchingKeys<T, V> & keyof Pick<T, RequiredKeys<T>>;
const getByPrimaryKey = <E>(list: E[], primaryKey: NonOptionalTypeMatchingKeys<E, string>): E => {
    ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接