您可以通过添加索引类型来强制属性类型,强制所有属性为一种类型:
interface AllStringProps {
[key: string]: string;
}
function f<T extends AllStringProps, K extends keyof T>(obj: T, key: K): string {
return obj[key].toLowerCase();
}
但是,这会限制您使用接受任何字符串作为属性的索引类型。
为了增加一点安全性,您可以将 sn-p 更改为
type AllStringProps<T> = {
[key in keyof T]: string;
}
function f<T extends AllStringProps<T>, K extends keyof T>(obj: T, key: K): string {
return obj[key].toLowerCase();
}
这里AllStringProps 类型强制T 中可用的所有键必须是字符串类型。强制所有可能的属性之前的 sn -p 必须是字符串类型。
在您的用例中,差别不大,但我总是更喜欢尽可能小的约束。
更新到 cmets 中的一个问题
比方说,我们只想允许T 的密钥子集。
我们可以从定义我们想要允许的所有键开始:
type AllowedKeys = { "s1" , "s2" };
type AllStringProps<AllowedKeys> = {
[key in keyof AllowedKeys]: string;
}
function f<T extends AllStringProps<AllowedKeys>,
K extends keyof AllowedKeys>(obj: T, key: K): string {
return obj[key].toLowerCase();
}
上面的 sn-p 将允许传递以下对象:
let t1 = {
s1: "Hello",
s2: "World",
other: 4
}
但不是这个
let t1 = {
s1: "Hello",
s2: 6,
other: 4
}